1
/*****************************************************************************
3
Copyright (C) 1996, 2010, Innobase Oy. 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., 51 Franklin
15
St, Fifth Floor, Boston, MA 02110-1301 USA
17
*****************************************************************************/
19
/**************************************************//**
20
@file include/btr0pcur.ic
21
The index tree persistent cursor
23
Created 2/23/1996 Heikki Tuuri
24
*******************************************************/
27
/*********************************************************//**
28
Gets the rel_pos field for a cursor whose position has been stored.
29
@return BTR_PCUR_ON, ... */
34
const btr_pcur_t* cursor) /*!< in: persistent cursor */
37
ut_ad(cursor->old_rec);
38
ut_ad(cursor->old_stored == BTR_PCUR_OLD_STORED);
39
ut_ad(cursor->pos_state == BTR_PCUR_WAS_POSITIONED
40
|| cursor->pos_state == BTR_PCUR_IS_POSITIONED);
42
return(cursor->rel_pos);
45
/*********************************************************//**
46
Sets the mtr field for a pcur. */
51
btr_pcur_t* cursor, /*!< in: persistent cursor */
52
mtr_t* mtr) /*!< in, own: mtr */
59
/*********************************************************//**
60
Gets the mtr field for a pcur.
66
btr_pcur_t* cursor) /*!< in: persistent cursor */
74
/*********************************************************//**
75
Returns the btr cursor component of a persistent cursor.
76
@return pointer to btr cursor component */
81
const btr_pcur_t* cursor) /*!< in: persistent cursor */
83
const btr_cur_t* btr_cur = &cursor->btr_cur;
84
return((btr_cur_t*) btr_cur);
87
/*********************************************************//**
88
Returns the page cursor component of a persistent cursor.
89
@return pointer to page cursor component */
92
btr_pcur_get_page_cur(
93
/*==================*/
94
const btr_pcur_t* cursor) /*!< in: persistent cursor */
96
return(btr_cur_get_page_cur(btr_pcur_get_btr_cur(cursor)));
98
#endif /* UNIV_DEBUG */
99
/*********************************************************//**
100
Returns the page of a persistent cursor.
101
@return pointer to the page */
106
btr_pcur_t* cursor) /*!< in: persistent cursor */
108
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
110
return(btr_cur_get_page(btr_pcur_get_btr_cur(cursor)));
113
/*********************************************************//**
114
Returns the buffer block of a persistent cursor.
115
@return pointer to the block */
120
btr_pcur_t* cursor) /*!< in: persistent cursor */
122
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
124
return(btr_cur_get_block(btr_pcur_get_btr_cur(cursor)));
127
/*********************************************************//**
128
Returns the record of a persistent cursor.
129
@return pointer to the record */
134
btr_pcur_t* cursor) /*!< in: persistent cursor */
136
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
137
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
139
return(btr_cur_get_rec(btr_pcur_get_btr_cur(cursor)));
142
/**************************************************************//**
143
Gets the up_match value for a pcur after a search.
144
@return number of matched fields at the cursor or to the right if
145
search mode was PAGE_CUR_GE, otherwise undefined */
148
btr_pcur_get_up_match(
149
/*==================*/
150
btr_pcur_t* cursor) /*!< in: memory buffer for persistent cursor */
152
btr_cur_t* btr_cursor;
154
ut_ad((cursor->pos_state == BTR_PCUR_WAS_POSITIONED)
155
|| (cursor->pos_state == BTR_PCUR_IS_POSITIONED));
157
btr_cursor = btr_pcur_get_btr_cur(cursor);
159
ut_ad(btr_cursor->up_match != ULINT_UNDEFINED);
161
return(btr_cursor->up_match);
164
/**************************************************************//**
165
Gets the low_match value for a pcur after a search.
166
@return number of matched fields at the cursor or to the right if
167
search mode was PAGE_CUR_LE, otherwise undefined */
170
btr_pcur_get_low_match(
171
/*===================*/
172
btr_pcur_t* cursor) /*!< in: memory buffer for persistent cursor */
174
btr_cur_t* btr_cursor;
176
ut_ad((cursor->pos_state == BTR_PCUR_WAS_POSITIONED)
177
|| (cursor->pos_state == BTR_PCUR_IS_POSITIONED));
179
btr_cursor = btr_pcur_get_btr_cur(cursor);
180
ut_ad(btr_cursor->low_match != ULINT_UNDEFINED);
182
return(btr_cursor->low_match);
185
/*********************************************************//**
186
Checks if the persistent cursor is after the last user record on
190
btr_pcur_is_after_last_on_page(
191
/*===========================*/
192
const btr_pcur_t* cursor) /*!< in: persistent cursor */
194
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
195
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
197
return(page_cur_is_after_last(btr_pcur_get_page_cur(cursor)));
200
/*********************************************************//**
201
Checks if the persistent cursor is before the first user record on
205
btr_pcur_is_before_first_on_page(
206
/*=============================*/
207
const btr_pcur_t* cursor) /*!< in: persistent cursor */
209
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
210
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
212
return(page_cur_is_before_first(btr_pcur_get_page_cur(cursor)));
215
/*********************************************************//**
216
Checks if the persistent cursor is on a user record. */
219
btr_pcur_is_on_user_rec(
220
/*====================*/
221
const btr_pcur_t* cursor) /*!< in: persistent cursor */
223
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
224
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
226
if (btr_pcur_is_before_first_on_page(cursor)
227
|| btr_pcur_is_after_last_on_page(cursor)) {
235
/*********************************************************//**
236
Checks if the persistent cursor is before the first user record in
240
btr_pcur_is_before_first_in_tree(
241
/*=============================*/
242
btr_pcur_t* cursor, /*!< in: persistent cursor */
243
mtr_t* mtr) /*!< in: mtr */
245
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
246
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
248
if (btr_page_get_prev(btr_pcur_get_page(cursor), mtr) != FIL_NULL) {
253
return(page_cur_is_before_first(btr_pcur_get_page_cur(cursor)));
256
/*********************************************************//**
257
Checks if the persistent cursor is after the last user record in
261
btr_pcur_is_after_last_in_tree(
262
/*===========================*/
263
btr_pcur_t* cursor, /*!< in: persistent cursor */
264
mtr_t* mtr) /*!< in: mtr */
266
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
267
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
269
if (btr_page_get_next(btr_pcur_get_page(cursor), mtr) != FIL_NULL) {
274
return(page_cur_is_after_last(btr_pcur_get_page_cur(cursor)));
277
/*********************************************************//**
278
Moves the persistent cursor to the next record on the same page. */
281
btr_pcur_move_to_next_on_page(
282
/*==========================*/
283
btr_pcur_t* cursor) /*!< in/out: persistent cursor */
285
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
286
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
288
page_cur_move_to_next(btr_pcur_get_page_cur(cursor));
290
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
293
/*********************************************************//**
294
Moves the persistent cursor to the previous record on the same page. */
297
btr_pcur_move_to_prev_on_page(
298
/*==========================*/
299
btr_pcur_t* cursor) /*!< in/out: persistent cursor */
301
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
302
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
304
page_cur_move_to_prev(btr_pcur_get_page_cur(cursor));
306
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
309
/*********************************************************//**
310
Moves the persistent cursor to the last record on the same page. */
313
btr_pcur_move_to_last_on_page(
314
/*==========================*/
315
btr_pcur_t* cursor, /*!< in: persistent cursor */
316
mtr_t* mtr) /*!< in: mtr */
319
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
321
page_cur_set_after_last(btr_pcur_get_block(cursor),
322
btr_pcur_get_page_cur(cursor));
324
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
327
/*********************************************************//**
328
Moves the persistent cursor to the next user record in the tree. If no user
329
records are left, the cursor ends up 'after last in tree'.
330
@return TRUE if the cursor moved forward, ending on a user record */
333
btr_pcur_move_to_next_user_rec(
334
/*===========================*/
335
btr_pcur_t* cursor, /*!< in: persistent cursor; NOTE that the
336
function may release the page latch */
337
mtr_t* mtr) /*!< in: mtr */
339
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
340
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
341
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
343
if (btr_pcur_is_after_last_on_page(cursor)) {
345
if (btr_pcur_is_after_last_in_tree(cursor, mtr)) {
350
btr_pcur_move_to_next_page(cursor, mtr);
352
btr_pcur_move_to_next_on_page(cursor);
355
if (btr_pcur_is_on_user_rec(cursor)) {
363
/*********************************************************//**
364
Moves the persistent cursor to the next record in the tree. If no records are
365
left, the cursor stays 'after last in tree'.
366
@return TRUE if the cursor was not after last in tree */
369
btr_pcur_move_to_next(
370
/*==================*/
371
btr_pcur_t* cursor, /*!< in: persistent cursor; NOTE that the
372
function may release the page latch */
373
mtr_t* mtr) /*!< in: mtr */
375
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
376
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
378
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
380
if (btr_pcur_is_after_last_on_page(cursor)) {
382
if (btr_pcur_is_after_last_in_tree(cursor, mtr)) {
387
btr_pcur_move_to_next_page(cursor, mtr);
392
btr_pcur_move_to_next_on_page(cursor);
397
/**************************************************************//**
398
Commits the mtr and sets the pcur latch mode to BTR_NO_LATCHES,
399
that is, the cursor becomes detached. If there have been modifications
400
to the page where pcur is positioned, this can be used instead of
401
btr_pcur_release_leaf. Function btr_pcur_store_position should be used
402
before calling this, if restoration of cursor is wanted later. */
405
btr_pcur_commit_specify_mtr(
406
/*========================*/
407
btr_pcur_t* pcur, /*!< in: persistent cursor */
408
mtr_t* mtr) /*!< in: mtr to commit */
410
ut_a(pcur->pos_state == BTR_PCUR_IS_POSITIONED);
412
pcur->latch_mode = BTR_NO_LATCHES;
416
pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
419
/**************************************************************//**
420
Sets the pcur latch mode to BTR_NO_LATCHES. */
425
btr_pcur_t* pcur) /*!< in: persistent cursor */
427
ut_a(pcur->pos_state == BTR_PCUR_IS_POSITIONED);
429
pcur->latch_mode = BTR_NO_LATCHES;
431
pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
434
/**************************************************************//**
435
Tests if a cursor is detached: that is the latch mode is BTR_NO_LATCHES.
436
@return TRUE if detached */
439
btr_pcur_is_detached(
440
/*=================*/
441
btr_pcur_t* pcur) /*!< in: persistent cursor */
443
if (pcur->latch_mode == BTR_NO_LATCHES) {
451
/**************************************************************//**
452
Sets the old_rec_buf field to NULL. */
457
btr_pcur_t* pcur) /*!< in: persistent cursor */
459
pcur->old_stored = BTR_PCUR_OLD_NOT_STORED;
460
pcur->old_rec_buf = NULL;
461
pcur->old_rec = NULL;
464
/**************************************************************//**
465
Initializes and opens a persistent cursor to an index tree. It should be
466
closed with btr_pcur_close. */
471
dict_index_t* index, /*!< in: index */
472
const dtuple_t* tuple, /*!< in: tuple on which search done */
473
ulint mode, /*!< in: PAGE_CUR_L, ...;
474
NOTE that if the search is made using a unique
475
prefix of a record, mode should be
476
PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
477
may end up on the previous page from the
479
ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */
480
btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
481
const char* file, /*!< in: file name */
482
ulint line, /*!< in: line where called */
483
mtr_t* mtr) /*!< in: mtr */
485
btr_cur_t* btr_cursor;
487
/* Initialize the cursor */
489
btr_pcur_init(cursor);
491
cursor->latch_mode = latch_mode;
492
cursor->search_mode = mode;
494
/* Search with the tree cursor */
496
btr_cursor = btr_pcur_get_btr_cur(cursor);
498
btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode,
499
btr_cursor, 0, file, line, mtr);
500
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
502
cursor->trx_if_known = NULL;
505
/**************************************************************//**
506
Opens an persistent cursor to an index tree without initializing the
510
btr_pcur_open_with_no_init_func(
511
/*============================*/
512
dict_index_t* index, /*!< in: index */
513
const dtuple_t* tuple, /*!< in: tuple on which search done */
514
ulint mode, /*!< in: PAGE_CUR_L, ...;
515
NOTE that if the search is made using a unique
516
prefix of a record, mode should be
517
PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
518
may end up on the previous page of the
520
ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ...;
521
NOTE that if has_search_latch != 0 then
522
we maybe do not acquire a latch on the cursor
523
page, but assume that the caller uses his
524
btr search latch to protect the record! */
525
btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
526
ulint has_search_latch,/*!< in: latch mode the caller
527
currently has on btr_search_latch:
529
const char* file, /*!< in: file name */
530
ulint line, /*!< in: line where called */
531
mtr_t* mtr) /*!< in: mtr */
533
btr_cur_t* btr_cursor;
535
cursor->latch_mode = latch_mode;
536
cursor->search_mode = mode;
538
/* Search with the tree cursor */
540
btr_cursor = btr_pcur_get_btr_cur(cursor);
542
btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode,
543
btr_cursor, has_search_latch,
545
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
547
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
549
cursor->trx_if_known = NULL;
552
/*****************************************************************//**
553
Opens a persistent cursor at either end of an index. */
556
btr_pcur_open_at_index_side(
557
/*========================*/
558
ibool from_left, /*!< in: TRUE if open to the low end,
559
FALSE if to the high end */
560
dict_index_t* index, /*!< in: index */
561
ulint latch_mode, /*!< in: latch mode */
562
btr_pcur_t* pcur, /*!< in: cursor */
563
ibool do_init, /*!< in: TRUE if should be initialized */
564
mtr_t* mtr) /*!< in: mtr */
566
pcur->latch_mode = latch_mode;
569
pcur->search_mode = PAGE_CUR_G;
571
pcur->search_mode = PAGE_CUR_L;
578
btr_cur_open_at_index_side(from_left, index, latch_mode,
579
btr_pcur_get_btr_cur(pcur), mtr);
580
pcur->pos_state = BTR_PCUR_IS_POSITIONED;
582
pcur->old_stored = BTR_PCUR_OLD_NOT_STORED;
584
pcur->trx_if_known = NULL;
587
/**********************************************************************//**
588
Positions a cursor at a randomly chosen position within a B-tree. */
591
btr_pcur_open_at_rnd_pos_func(
592
/*==========================*/
593
dict_index_t* index, /*!< in: index */
594
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */
595
btr_pcur_t* cursor, /*!< in/out: B-tree pcur */
596
const char* file, /*!< in: file name */
597
ulint line, /*!< in: line where called */
598
mtr_t* mtr) /*!< in: mtr */
600
/* Initialize the cursor */
602
cursor->latch_mode = latch_mode;
603
cursor->search_mode = PAGE_CUR_G;
605
btr_pcur_init(cursor);
607
btr_cur_open_at_rnd_pos_func(index, latch_mode,
608
btr_pcur_get_btr_cur(cursor),
610
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
611
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
613
cursor->trx_if_known = NULL;
616
/**************************************************************//**
617
Frees the possible memory heap of a persistent cursor and sets the latch
618
mode of the persistent cursor to BTR_NO_LATCHES. */
623
btr_pcur_t* cursor) /*!< in: persistent cursor */
625
if (cursor->old_rec_buf != NULL) {
627
mem_free(cursor->old_rec_buf);
629
cursor->old_rec = NULL;
630
cursor->old_rec_buf = NULL;
633
cursor->btr_cur.page_cur.rec = NULL;
634
cursor->btr_cur.page_cur.block = NULL;
635
cursor->old_rec = NULL;
636
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
638
cursor->latch_mode = BTR_NO_LATCHES;
639
cursor->pos_state = BTR_PCUR_NOT_POSITIONED;
641
cursor->trx_if_known = NULL;