1
/*****************************************************************************
3
Copyright (c) 1996, 2009, 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., 59 Temple
15
Place, Suite 330, Boston, MA 02111-1307 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 pcur 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. */
407
btr_pcur_t* pcur) /*!< in: persistent cursor */
409
ut_a(pcur->pos_state == BTR_PCUR_IS_POSITIONED);
411
pcur->latch_mode = BTR_NO_LATCHES;
413
mtr_commit(pcur->mtr);
415
pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
418
/**************************************************************//**
419
Differs from btr_pcur_commit in that we can specify the mtr to commit. */
422
btr_pcur_commit_specify_mtr(
423
/*========================*/
424
btr_pcur_t* pcur, /*!< in: persistent cursor */
425
mtr_t* mtr) /*!< in: mtr to commit */
427
ut_a(pcur->pos_state == BTR_PCUR_IS_POSITIONED);
429
pcur->latch_mode = BTR_NO_LATCHES;
433
pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
436
/**************************************************************//**
437
Sets the pcur latch mode to BTR_NO_LATCHES. */
442
btr_pcur_t* pcur) /*!< in: persistent cursor */
444
ut_a(pcur->pos_state == BTR_PCUR_IS_POSITIONED);
446
pcur->latch_mode = BTR_NO_LATCHES;
448
pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
451
/**************************************************************//**
452
Tests if a cursor is detached: that is the latch mode is BTR_NO_LATCHES.
453
@return TRUE if detached */
456
btr_pcur_is_detached(
457
/*=================*/
458
btr_pcur_t* pcur) /*!< in: persistent cursor */
460
if (pcur->latch_mode == BTR_NO_LATCHES) {
468
/**************************************************************//**
469
Sets the old_rec_buf field to NULL. */
474
btr_pcur_t* pcur) /*!< in: persistent cursor */
476
pcur->old_stored = BTR_PCUR_OLD_NOT_STORED;
477
pcur->old_rec_buf = NULL;
478
pcur->old_rec = NULL;
481
/**************************************************************//**
482
Initializes and opens a persistent cursor to an index tree. It should be
483
closed with btr_pcur_close. */
488
dict_index_t* index, /*!< in: index */
489
const dtuple_t* tuple, /*!< in: tuple on which search done */
490
ulint mode, /*!< in: PAGE_CUR_L, ...;
491
NOTE that if the search is made using a unique
492
prefix of a record, mode should be
493
PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
494
may end up on the previous page from the
496
ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */
497
btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
498
mtr_t* mtr) /*!< in: mtr */
500
btr_cur_t* btr_cursor;
502
/* Initialize the cursor */
504
btr_pcur_init(cursor);
506
cursor->latch_mode = latch_mode;
507
cursor->search_mode = mode;
509
/* Search with the tree cursor */
511
btr_cursor = btr_pcur_get_btr_cur(cursor);
513
btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode,
515
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
517
cursor->trx_if_known = NULL;
520
/**************************************************************//**
521
Opens an persistent cursor to an index tree without initializing the
525
btr_pcur_open_with_no_init(
526
/*=======================*/
527
dict_index_t* index, /*!< in: index */
528
const dtuple_t* tuple, /*!< in: tuple on which search done */
529
ulint mode, /*!< in: PAGE_CUR_L, ...;
530
NOTE that if the search is made using a unique
531
prefix of a record, mode should be
532
PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
533
may end up on the previous page of the
535
ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ...;
536
NOTE that if has_search_latch != 0 then
537
we maybe do not acquire a latch on the cursor
538
page, but assume that the caller uses his
539
btr search latch to protect the record! */
540
btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
541
ulint has_search_latch,/*!< in: latch mode the caller
542
currently has on btr_search_latch:
544
mtr_t* mtr) /*!< in: mtr */
546
btr_cur_t* btr_cursor;
548
cursor->latch_mode = latch_mode;
549
cursor->search_mode = mode;
551
/* Search with the tree cursor */
553
btr_cursor = btr_pcur_get_btr_cur(cursor);
555
btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode,
556
btr_cursor, has_search_latch, mtr);
557
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
559
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
561
cursor->trx_if_known = NULL;
564
/*****************************************************************//**
565
Opens a persistent cursor at either end of an index. */
568
btr_pcur_open_at_index_side(
569
/*========================*/
570
ibool from_left, /*!< in: TRUE if open to the low end,
571
FALSE if to the high end */
572
dict_index_t* index, /*!< in: index */
573
ulint latch_mode, /*!< in: latch mode */
574
btr_pcur_t* pcur, /*!< in: cursor */
575
ibool do_init, /*!< in: TRUE if should be initialized */
576
mtr_t* mtr) /*!< in: mtr */
578
pcur->latch_mode = latch_mode;
581
pcur->search_mode = PAGE_CUR_G;
583
pcur->search_mode = PAGE_CUR_L;
590
btr_cur_open_at_index_side(from_left, index, latch_mode,
591
btr_pcur_get_btr_cur(pcur), mtr);
592
pcur->pos_state = BTR_PCUR_IS_POSITIONED;
594
pcur->old_stored = BTR_PCUR_OLD_NOT_STORED;
596
pcur->trx_if_known = NULL;
599
/**********************************************************************//**
600
Positions a cursor at a randomly chosen position within a B-tree. */
603
btr_pcur_open_at_rnd_pos(
604
/*=====================*/
605
dict_index_t* index, /*!< in: index */
606
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */
607
btr_pcur_t* cursor, /*!< in/out: B-tree pcur */
608
mtr_t* mtr) /*!< in: mtr */
610
/* Initialize the cursor */
612
cursor->latch_mode = latch_mode;
613
cursor->search_mode = PAGE_CUR_G;
615
btr_pcur_init(cursor);
617
btr_cur_open_at_rnd_pos(index, latch_mode,
618
btr_pcur_get_btr_cur(cursor), mtr);
619
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
620
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
622
cursor->trx_if_known = NULL;
625
/**************************************************************//**
626
Frees the possible memory heap of a persistent cursor and sets the latch
627
mode of the persistent cursor to BTR_NO_LATCHES. */
632
btr_pcur_t* cursor) /*!< in: persistent cursor */
634
if (cursor->old_rec_buf != NULL) {
636
mem_free(cursor->old_rec_buf);
638
cursor->old_rec = NULL;
639
cursor->old_rec_buf = NULL;
642
cursor->btr_cur.page_cur.rec = NULL;
643
cursor->btr_cur.page_cur.block = NULL;
644
cursor->old_rec = NULL;
645
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
647
cursor->latch_mode = BTR_NO_LATCHES;
648
cursor->pos_state = BTR_PCUR_NOT_POSITIONED;
650
cursor->trx_if_known = NULL;