1
/******************************************************
2
The index tree persistent cursor
6
Created 2/23/1996 Heikki Tuuri
7
*******************************************************/
10
/*************************************************************
11
Gets the rel_pos field for a cursor whose position has been stored. */
16
/* out: BTR_PCUR_ON, ... */
17
const btr_pcur_t* cursor) /* in: persistent cursor */
20
ut_ad(cursor->old_rec);
21
ut_ad(cursor->old_stored == BTR_PCUR_OLD_STORED);
22
ut_ad(cursor->pos_state == BTR_PCUR_WAS_POSITIONED
23
|| cursor->pos_state == BTR_PCUR_IS_POSITIONED);
25
return(cursor->rel_pos);
28
/*************************************************************
29
Sets the mtr field for a pcur. */
34
btr_pcur_t* cursor, /* in: persistent cursor */
35
mtr_t* mtr) /* in, own: mtr */
42
/*************************************************************
43
Gets the mtr field for a pcur. */
49
btr_pcur_t* cursor) /* in: persistent cursor */
57
/*************************************************************
58
Returns the btr cursor component of a persistent cursor. */
64
btr cursor component */
65
const btr_pcur_t* cursor) /* in: persistent cursor */
67
const btr_cur_t* btr_cur = &cursor->btr_cur;
68
return((btr_cur_t*) btr_cur);
71
/*************************************************************
72
Returns the page cursor component of a persistent cursor. */
75
btr_pcur_get_page_cur(
76
/*==================*/
77
/* out: pointer to page cursor
79
const btr_pcur_t* cursor) /* in: persistent cursor */
81
return(btr_cur_get_page_cur(btr_pcur_get_btr_cur(cursor)));
83
#endif /* UNIV_DEBUG */
84
/*************************************************************
85
Returns the page of a persistent cursor. */
90
/* out: pointer to the page */
91
btr_pcur_t* cursor) /* in: persistent cursor */
93
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
95
return(btr_cur_get_page(btr_pcur_get_btr_cur(cursor)));
98
/*************************************************************
99
Returns the buffer block of a persistent cursor. */
104
/* out: pointer to the block */
105
btr_pcur_t* cursor) /* in: persistent cursor */
107
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
109
return(btr_cur_get_block(btr_pcur_get_btr_cur(cursor)));
112
/*************************************************************
113
Returns the record of a persistent cursor. */
118
/* out: pointer to the record */
119
btr_pcur_t* cursor) /* in: persistent cursor */
121
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
122
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
124
return(btr_cur_get_rec(btr_pcur_get_btr_cur(cursor)));
127
/******************************************************************
128
Gets the up_match value for a pcur after a search. */
131
btr_pcur_get_up_match(
132
/*==================*/
133
/* out: number of matched fields at the cursor
134
or to the right if search mode was PAGE_CUR_GE,
135
otherwise undefined */
136
btr_pcur_t* cursor) /* in: memory buffer for persistent cursor */
138
btr_cur_t* btr_cursor;
140
ut_ad((cursor->pos_state == BTR_PCUR_WAS_POSITIONED)
141
|| (cursor->pos_state == BTR_PCUR_IS_POSITIONED));
143
btr_cursor = btr_pcur_get_btr_cur(cursor);
145
ut_ad(btr_cursor->up_match != ULINT_UNDEFINED);
147
return(btr_cursor->up_match);
150
/******************************************************************
151
Gets the low_match value for a pcur after a search. */
154
btr_pcur_get_low_match(
155
/*===================*/
156
/* out: number of matched fields at the cursor
157
or to the right if search mode was PAGE_CUR_LE,
158
otherwise undefined */
159
btr_pcur_t* cursor) /* in: memory buffer for persistent cursor */
161
btr_cur_t* btr_cursor;
163
ut_ad((cursor->pos_state == BTR_PCUR_WAS_POSITIONED)
164
|| (cursor->pos_state == BTR_PCUR_IS_POSITIONED));
166
btr_cursor = btr_pcur_get_btr_cur(cursor);
167
ut_ad(btr_cursor->low_match != ULINT_UNDEFINED);
169
return(btr_cursor->low_match);
172
/*************************************************************
173
Checks if the persistent cursor is after the last user record on
177
btr_pcur_is_after_last_on_page(
178
/*===========================*/
179
const btr_pcur_t* cursor) /* in: persistent cursor */
181
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
182
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
184
return(page_cur_is_after_last(btr_pcur_get_page_cur(cursor)));
187
/*************************************************************
188
Checks if the persistent cursor is before the first user record on
192
btr_pcur_is_before_first_on_page(
193
/*=============================*/
194
const btr_pcur_t* cursor) /* in: persistent cursor */
196
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
197
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
199
return(page_cur_is_before_first(btr_pcur_get_page_cur(cursor)));
202
/*************************************************************
203
Checks if the persistent cursor is on a user record. */
206
btr_pcur_is_on_user_rec(
207
/*====================*/
208
const btr_pcur_t* cursor) /* in: persistent cursor */
210
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
211
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
213
if (btr_pcur_is_before_first_on_page(cursor)
214
|| btr_pcur_is_after_last_on_page(cursor)) {
222
/*************************************************************
223
Checks if the persistent cursor is before the first user record in
227
btr_pcur_is_before_first_in_tree(
228
/*=============================*/
229
btr_pcur_t* cursor, /* in: persistent cursor */
230
mtr_t* mtr) /* in: mtr */
232
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
233
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
235
if (btr_page_get_prev(btr_pcur_get_page(cursor), mtr) != FIL_NULL) {
240
return(page_cur_is_before_first(btr_pcur_get_page_cur(cursor)));
243
/*************************************************************
244
Checks if the persistent cursor is after the last user record in
248
btr_pcur_is_after_last_in_tree(
249
/*===========================*/
250
btr_pcur_t* cursor, /* in: persistent cursor */
251
mtr_t* mtr) /* in: mtr */
253
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
254
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
256
if (btr_page_get_next(btr_pcur_get_page(cursor), mtr) != FIL_NULL) {
261
return(page_cur_is_after_last(btr_pcur_get_page_cur(cursor)));
264
/*************************************************************
265
Moves the persistent cursor to the next record on the same page. */
268
btr_pcur_move_to_next_on_page(
269
/*==========================*/
270
btr_pcur_t* cursor) /* in/out: persistent cursor */
272
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
273
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
275
page_cur_move_to_next(btr_pcur_get_page_cur(cursor));
277
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
280
/*************************************************************
281
Moves the persistent cursor to the previous record on the same page. */
284
btr_pcur_move_to_prev_on_page(
285
/*==========================*/
286
btr_pcur_t* cursor) /* in/out: persistent cursor */
288
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
289
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
291
page_cur_move_to_prev(btr_pcur_get_page_cur(cursor));
293
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
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 */
306
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
308
page_cur_set_after_last(btr_pcur_get_block(cursor),
309
btr_pcur_get_page_cur(cursor));
311
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
314
/*************************************************************
315
Moves the persistent cursor to the next user record in the tree. If no user
316
records are left, the cursor ends up 'after last in tree'. */
319
btr_pcur_move_to_next_user_rec(
320
/*===========================*/
321
/* out: TRUE if the cursor moved forward,
322
ending on a user record */
323
btr_pcur_t* cursor, /* in: persistent cursor; NOTE that the
324
function may release the page latch */
325
mtr_t* mtr) /* in: mtr */
327
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
328
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
329
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
331
if (btr_pcur_is_after_last_on_page(cursor)) {
333
if (btr_pcur_is_after_last_in_tree(cursor, mtr)) {
338
btr_pcur_move_to_next_page(cursor, mtr);
340
btr_pcur_move_to_next_on_page(cursor);
343
if (btr_pcur_is_on_user_rec(cursor)) {
351
/*************************************************************
352
Moves the persistent cursor to the next record in the tree. If no records are
353
left, the cursor stays 'after last in tree'. */
356
btr_pcur_move_to_next(
357
/*==================*/
358
/* out: TRUE if the cursor was not after last
360
btr_pcur_t* cursor, /* in: persistent cursor; NOTE that the
361
function may release the page latch */
362
mtr_t* mtr) /* in: mtr */
364
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
365
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
367
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
369
if (btr_pcur_is_after_last_on_page(cursor)) {
371
if (btr_pcur_is_after_last_in_tree(cursor, mtr)) {
376
btr_pcur_move_to_next_page(cursor, mtr);
381
btr_pcur_move_to_next_on_page(cursor);
386
/******************************************************************
387
Commits the pcur mtr and sets the pcur latch mode to BTR_NO_LATCHES,
388
that is, the cursor becomes detached. If there have been modifications
389
to the page where pcur is positioned, this can be used instead of
390
btr_pcur_release_leaf. Function btr_pcur_store_position should be used
391
before calling this, if restoration of cursor is wanted later. */
396
btr_pcur_t* pcur) /* in: persistent cursor */
398
ut_a(pcur->pos_state == BTR_PCUR_IS_POSITIONED);
400
pcur->latch_mode = BTR_NO_LATCHES;
402
mtr_commit(pcur->mtr);
404
pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
407
/******************************************************************
408
Differs from btr_pcur_commit in that we can specify the mtr to commit. */
411
btr_pcur_commit_specify_mtr(
412
/*========================*/
413
btr_pcur_t* pcur, /* in: persistent cursor */
414
mtr_t* mtr) /* in: mtr to commit */
416
ut_a(pcur->pos_state == BTR_PCUR_IS_POSITIONED);
418
pcur->latch_mode = BTR_NO_LATCHES;
422
pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
425
/******************************************************************
426
Sets the pcur latch mode to BTR_NO_LATCHES. */
431
btr_pcur_t* pcur) /* in: persistent cursor */
433
ut_a(pcur->pos_state == BTR_PCUR_IS_POSITIONED);
435
pcur->latch_mode = BTR_NO_LATCHES;
437
pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
440
/******************************************************************
441
Tests if a cursor is detached: that is the latch mode is BTR_NO_LATCHES. */
444
btr_pcur_is_detached(
445
/*=================*/
446
/* out: TRUE if detached */
447
btr_pcur_t* pcur) /* in: persistent cursor */
449
if (pcur->latch_mode == BTR_NO_LATCHES) {
457
/******************************************************************
458
Sets the old_rec_buf field to NULL. */
463
btr_pcur_t* pcur) /* in: persistent cursor */
465
pcur->old_stored = BTR_PCUR_OLD_NOT_STORED;
466
pcur->old_rec_buf = NULL;
467
pcur->old_rec = NULL;
470
/******************************************************************
471
Initializes and opens a persistent cursor to an index tree. It should be
472
closed with btr_pcur_close. */
477
dict_index_t* index, /* in: index */
478
const dtuple_t* tuple, /* in: tuple on which search done */
479
ulint mode, /* in: PAGE_CUR_L, ...;
480
NOTE that if the search is made using a unique
481
prefix of a record, mode should be
482
PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
483
may end up on the previous page from the
485
ulint latch_mode,/* in: BTR_SEARCH_LEAF, ... */
486
btr_pcur_t* cursor, /* in: memory buffer for persistent cursor */
487
mtr_t* mtr) /* in: mtr */
489
btr_cur_t* btr_cursor;
491
/* Initialize the cursor */
493
btr_pcur_init(cursor);
495
cursor->latch_mode = latch_mode;
496
cursor->search_mode = mode;
498
/* Search with the tree cursor */
500
btr_cursor = btr_pcur_get_btr_cur(cursor);
502
btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode,
504
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
506
cursor->trx_if_known = NULL;
509
/******************************************************************
510
Opens an persistent cursor to an index tree without initializing the
514
btr_pcur_open_with_no_init(
515
/*=======================*/
516
dict_index_t* index, /* in: index */
517
const dtuple_t* tuple, /* in: tuple on which search done */
518
ulint mode, /* in: PAGE_CUR_L, ...;
519
NOTE that if the search is made using a unique
520
prefix of a record, mode should be
521
PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
522
may end up on the previous page of the
524
ulint latch_mode,/* in: BTR_SEARCH_LEAF, ...;
525
NOTE that if has_search_latch != 0 then
526
we maybe do not acquire a latch on the cursor
527
page, but assume that the caller uses his
528
btr search latch to protect the record! */
529
btr_pcur_t* cursor, /* in: memory buffer for persistent cursor */
530
ulint has_search_latch,/* in: latch mode the caller
531
currently has on btr_search_latch:
533
mtr_t* mtr) /* in: mtr */
535
btr_cur_t* btr_cursor;
537
cursor->latch_mode = latch_mode;
538
cursor->search_mode = mode;
540
/* Search with the tree cursor */
542
btr_cursor = btr_pcur_get_btr_cur(cursor);
544
btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode,
545
btr_cursor, has_search_latch, mtr);
546
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
548
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
550
cursor->trx_if_known = NULL;
553
/*********************************************************************
554
Opens a persistent cursor at either end of an index. */
557
btr_pcur_open_at_index_side(
558
/*========================*/
559
ibool from_left, /* in: TRUE if open to the low end,
560
FALSE if to the high end */
561
dict_index_t* index, /* in: index */
562
ulint latch_mode, /* in: latch mode */
563
btr_pcur_t* pcur, /* in: cursor */
564
ibool do_init, /* in: TRUE if should be initialized */
565
mtr_t* mtr) /* in: mtr */
567
pcur->latch_mode = latch_mode;
570
pcur->search_mode = PAGE_CUR_G;
572
pcur->search_mode = PAGE_CUR_L;
579
btr_cur_open_at_index_side(from_left, index, latch_mode,
580
btr_pcur_get_btr_cur(pcur), mtr);
581
pcur->pos_state = BTR_PCUR_IS_POSITIONED;
583
pcur->old_stored = BTR_PCUR_OLD_NOT_STORED;
585
pcur->trx_if_known = NULL;
588
/**************************************************************************
589
Positions a cursor at a randomly chosen position within a B-tree. */
592
btr_pcur_open_at_rnd_pos(
593
/*=====================*/
594
dict_index_t* index, /* in: index */
595
ulint latch_mode, /* in: BTR_SEARCH_LEAF, ... */
596
btr_pcur_t* cursor, /* in/out: B-tree pcur */
597
mtr_t* mtr) /* in: mtr */
599
/* Initialize the cursor */
601
cursor->latch_mode = latch_mode;
602
cursor->search_mode = PAGE_CUR_G;
604
btr_pcur_init(cursor);
606
btr_cur_open_at_rnd_pos(index, latch_mode,
607
btr_pcur_get_btr_cur(cursor), mtr);
608
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
609
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
611
cursor->trx_if_known = NULL;
614
/******************************************************************
615
Frees the possible memory heap of a persistent cursor and sets the latch
616
mode of the persistent cursor to BTR_NO_LATCHES. */
621
btr_pcur_t* cursor) /* in: persistent cursor */
623
if (cursor->old_rec_buf != NULL) {
625
mem_free(cursor->old_rec_buf);
627
cursor->old_rec = NULL;
628
cursor->old_rec_buf = NULL;
631
cursor->btr_cur.page_cur.rec = NULL;
632
cursor->btr_cur.page_cur.block = NULL;
633
cursor->old_rec = NULL;
634
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
636
cursor->latch_mode = BTR_NO_LATCHES;
637
cursor->pos_state = BTR_PCUR_NOT_POSITIONED;
639
cursor->trx_if_known = NULL;