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
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 */
56
/*************************************************************
57
Returns the btr cursor component of a persistent cursor. */
62
/* out: pointer to btr cursor component */
63
btr_pcur_t* cursor) /* in: persistent cursor */
65
return(&(cursor->btr_cur));
68
/*************************************************************
69
Returns the page cursor component of a persistent cursor. */
72
btr_pcur_get_page_cur(
73
/*==================*/
74
/* out: pointer to page cursor component */
75
btr_pcur_t* cursor) /* in: persistent cursor */
77
return(btr_cur_get_page_cur(&(cursor->btr_cur)));
80
/*************************************************************
81
Returns the page of a persistent cursor. */
86
/* out: pointer to the page */
87
btr_pcur_t* cursor) /* in: persistent cursor */
89
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
91
return(page_cur_get_page(btr_pcur_get_page_cur(cursor)));
94
/*************************************************************
95
Returns the record of a persistent cursor. */
100
/* out: pointer to the record */
101
btr_pcur_t* cursor) /* in: persistent cursor */
103
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
104
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
106
return(page_cur_get_rec(btr_pcur_get_page_cur(cursor)));
109
/******************************************************************
110
Gets the up_match value for a pcur after a search. */
113
btr_pcur_get_up_match(
114
/*==================*/
115
/* out: number of matched fields at the cursor
116
or to the right if search mode was PAGE_CUR_GE,
117
otherwise undefined */
118
btr_pcur_t* cursor) /* in: memory buffer for persistent cursor */
120
btr_cur_t* btr_cursor;
122
ut_ad((cursor->pos_state == BTR_PCUR_WAS_POSITIONED)
123
|| (cursor->pos_state == BTR_PCUR_IS_POSITIONED));
125
btr_cursor = btr_pcur_get_btr_cur(cursor);
127
ut_ad(btr_cursor->up_match != ULINT_UNDEFINED);
129
return(btr_cursor->up_match);
132
/******************************************************************
133
Gets the low_match value for a pcur after a search. */
136
btr_pcur_get_low_match(
137
/*===================*/
138
/* out: number of matched fields at the cursor
139
or to the right if search mode was PAGE_CUR_LE,
140
otherwise undefined */
141
btr_pcur_t* cursor) /* in: memory buffer for persistent cursor */
143
btr_cur_t* btr_cursor;
145
ut_ad((cursor->pos_state == BTR_PCUR_WAS_POSITIONED)
146
|| (cursor->pos_state == BTR_PCUR_IS_POSITIONED));
148
btr_cursor = btr_pcur_get_btr_cur(cursor);
149
ut_ad(btr_cursor->low_match != ULINT_UNDEFINED);
151
return(btr_cursor->low_match);
154
/*************************************************************
155
Checks if the persistent cursor is after the last user record on
159
btr_pcur_is_after_last_on_page(
160
/*===========================*/
161
btr_pcur_t* cursor, /* in: persistent cursor */
162
mtr_t* mtr) /* in: mtr */
165
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
166
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
168
return(page_cur_is_after_last(btr_pcur_get_page_cur(cursor)));
171
/*************************************************************
172
Checks if the persistent cursor is before the first user record on
176
btr_pcur_is_before_first_on_page(
177
/*=============================*/
178
btr_pcur_t* cursor, /* in: persistent cursor */
179
mtr_t* mtr) /* in: mtr */
182
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
183
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
185
return(page_cur_is_before_first(btr_pcur_get_page_cur(cursor)));
188
/*************************************************************
189
Checks if the persistent cursor is on a user record. */
192
btr_pcur_is_on_user_rec(
193
/*====================*/
194
btr_pcur_t* cursor, /* in: persistent cursor */
195
mtr_t* mtr) /* in: mtr */
197
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
198
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
200
if ((btr_pcur_is_before_first_on_page(cursor, mtr))
201
|| (btr_pcur_is_after_last_on_page(cursor, mtr))) {
209
/*************************************************************
210
Checks if the persistent cursor is before the first user record in
214
btr_pcur_is_before_first_in_tree(
215
/*=============================*/
216
btr_pcur_t* cursor, /* in: persistent cursor */
217
mtr_t* mtr) /* in: mtr */
219
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
220
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
222
if (btr_page_get_prev(btr_pcur_get_page(cursor), mtr) != FIL_NULL) {
227
return(page_cur_is_before_first(btr_pcur_get_page_cur(cursor)));
230
/*************************************************************
231
Checks if the persistent cursor is after the last user record in
235
btr_pcur_is_after_last_in_tree(
236
/*===========================*/
237
btr_pcur_t* cursor, /* in: persistent cursor */
238
mtr_t* mtr) /* in: mtr */
240
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
241
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
243
if (btr_page_get_next(btr_pcur_get_page(cursor), mtr) != FIL_NULL) {
248
return(page_cur_is_after_last(btr_pcur_get_page_cur(cursor)));
251
/*************************************************************
252
Moves the persistent cursor to the next record on the same page. */
255
btr_pcur_move_to_next_on_page(
256
/*==========================*/
257
btr_pcur_t* cursor, /* in: persistent cursor */
258
mtr_t* mtr) /* in: mtr */
261
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
262
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
264
page_cur_move_to_next(btr_pcur_get_page_cur(cursor));
266
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
269
/*************************************************************
270
Moves the persistent cursor to the previous record on the same page. */
273
btr_pcur_move_to_prev_on_page(
274
/*==========================*/
275
btr_pcur_t* cursor, /* in: persistent cursor */
276
mtr_t* mtr) /* in: mtr */
279
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
280
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
282
page_cur_move_to_prev(btr_pcur_get_page_cur(cursor));
284
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
287
/*************************************************************
288
Moves the persistent cursor to the last record on the same page. */
291
btr_pcur_move_to_last_on_page(
292
/*==========================*/
293
btr_pcur_t* cursor, /* in: persistent cursor */
294
mtr_t* mtr) /* in: mtr */
297
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
299
page_cur_set_after_last(buf_frame_align(btr_pcur_get_rec(cursor)),
300
btr_pcur_get_page_cur(cursor));
302
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
305
/*************************************************************
306
Moves the persistent cursor to the next user record in the tree. If no user
307
records are left, the cursor ends up 'after last in tree'. */
310
btr_pcur_move_to_next_user_rec(
311
/*===========================*/
312
/* out: TRUE if the cursor moved forward,
313
ending on a user record */
314
btr_pcur_t* cursor, /* in: persistent cursor; NOTE that the
315
function may release the page latch */
316
mtr_t* mtr) /* in: mtr */
318
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
319
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
320
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
322
if (btr_pcur_is_after_last_on_page(cursor, mtr)) {
324
if (btr_pcur_is_after_last_in_tree(cursor, mtr)) {
329
btr_pcur_move_to_next_page(cursor, mtr);
331
btr_pcur_move_to_next_on_page(cursor, mtr);
334
if (btr_pcur_is_on_user_rec(cursor, mtr)) {
342
/*************************************************************
343
Moves the persistent cursor to the next record in the tree. If no records are
344
left, the cursor stays 'after last in tree'. */
347
btr_pcur_move_to_next(
348
/*==================*/
349
/* out: TRUE if the cursor was not after last
351
btr_pcur_t* cursor, /* in: persistent cursor; NOTE that the
352
function may release the page latch */
353
mtr_t* mtr) /* in: mtr */
355
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
356
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
358
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
360
if (btr_pcur_is_after_last_on_page(cursor, mtr)) {
362
if (btr_pcur_is_after_last_in_tree(cursor, mtr)) {
367
btr_pcur_move_to_next_page(cursor, mtr);
372
btr_pcur_move_to_next_on_page(cursor, mtr);
377
/******************************************************************
378
Commits the pcur mtr and sets the pcur latch mode to BTR_NO_LATCHES,
379
that is, the cursor becomes detached. If there have been modifications
380
to the page where pcur is positioned, this can be used instead of
381
btr_pcur_release_leaf. Function btr_pcur_store_position should be used
382
before calling this, if restoration of cursor is wanted later. */
387
btr_pcur_t* pcur) /* in: persistent cursor */
389
ut_a(pcur->pos_state == BTR_PCUR_IS_POSITIONED);
391
pcur->latch_mode = BTR_NO_LATCHES;
393
mtr_commit(pcur->mtr);
395
pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
398
/******************************************************************
399
Differs from btr_pcur_commit in that we can specify the mtr to commit. */
402
btr_pcur_commit_specify_mtr(
403
/*========================*/
404
btr_pcur_t* pcur, /* in: persistent cursor */
405
mtr_t* mtr) /* in: mtr to commit */
407
ut_a(pcur->pos_state == BTR_PCUR_IS_POSITIONED);
409
pcur->latch_mode = BTR_NO_LATCHES;
413
pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
416
/******************************************************************
417
Sets the pcur latch mode to BTR_NO_LATCHES. */
422
btr_pcur_t* pcur) /* in: persistent cursor */
424
ut_a(pcur->pos_state == BTR_PCUR_IS_POSITIONED);
426
pcur->latch_mode = BTR_NO_LATCHES;
428
pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
431
/******************************************************************
432
Tests if a cursor is detached: that is the latch mode is BTR_NO_LATCHES. */
435
btr_pcur_is_detached(
436
/*=================*/
437
/* out: TRUE if detached */
438
btr_pcur_t* pcur) /* in: persistent cursor */
440
if (pcur->latch_mode == BTR_NO_LATCHES) {
448
/******************************************************************
449
Sets the old_rec_buf field to NULL. */
454
btr_pcur_t* pcur) /* in: persistent cursor */
456
pcur->old_stored = BTR_PCUR_OLD_NOT_STORED;
457
pcur->old_rec_buf = NULL;
458
pcur->old_rec = NULL;
461
/******************************************************************
462
Initializes and opens a persistent cursor to an index tree. It should be
463
closed with btr_pcur_close. */
468
dict_index_t* index, /* in: index */
469
dtuple_t* tuple, /* in: tuple on which search done */
470
ulint mode, /* in: PAGE_CUR_L, ...;
471
NOTE that if the search is made using a unique
472
prefix of a record, mode should be
473
PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
474
may end up on the previous page from the
476
ulint latch_mode,/* in: BTR_SEARCH_LEAF, ... */
477
btr_pcur_t* cursor, /* in: memory buffer for persistent cursor */
478
mtr_t* mtr) /* in: mtr */
480
btr_cur_t* btr_cursor;
482
/* Initialize the cursor */
484
btr_pcur_init(cursor);
486
cursor->latch_mode = latch_mode;
487
cursor->search_mode = mode;
489
/* Search with the tree cursor */
491
btr_cursor = btr_pcur_get_btr_cur(cursor);
493
btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode,
495
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
497
cursor->trx_if_known = NULL;
500
/******************************************************************
501
Opens an persistent cursor to an index tree without initializing the
505
btr_pcur_open_with_no_init(
506
/*=======================*/
507
dict_index_t* index, /* in: index */
508
dtuple_t* tuple, /* in: tuple on which search done */
509
ulint mode, /* in: PAGE_CUR_L, ...;
510
NOTE that if the search is made using a unique
511
prefix of a record, mode should be
512
PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
513
may end up on the previous page of the
515
ulint latch_mode,/* in: BTR_SEARCH_LEAF, ...;
516
NOTE that if has_search_latch != 0 then
517
we maybe do not acquire a latch on the cursor
518
page, but assume that the caller uses his
519
btr search latch to protect the record! */
520
btr_pcur_t* cursor, /* in: memory buffer for persistent cursor */
521
ulint has_search_latch,/* in: latch mode the caller
522
currently has on btr_search_latch:
524
mtr_t* mtr) /* in: mtr */
526
btr_cur_t* btr_cursor;
528
cursor->latch_mode = latch_mode;
529
cursor->search_mode = mode;
531
/* Search with the tree cursor */
533
btr_cursor = btr_pcur_get_btr_cur(cursor);
535
btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode,
536
btr_cursor, has_search_latch, mtr);
537
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
539
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
541
cursor->trx_if_known = NULL;
544
/*********************************************************************
545
Opens a persistent cursor at either end of an index. */
548
btr_pcur_open_at_index_side(
549
/*========================*/
550
ibool from_left, /* in: TRUE if open to the low end,
551
FALSE if to the high end */
552
dict_index_t* index, /* in: index */
553
ulint latch_mode, /* in: latch mode */
554
btr_pcur_t* pcur, /* in: cursor */
555
ibool do_init, /* in: TRUE if should be initialized */
556
mtr_t* mtr) /* in: mtr */
558
pcur->latch_mode = latch_mode;
561
pcur->search_mode = PAGE_CUR_G;
563
pcur->search_mode = PAGE_CUR_L;
570
btr_cur_open_at_index_side(from_left, index, latch_mode,
571
btr_pcur_get_btr_cur(pcur), mtr);
572
pcur->pos_state = BTR_PCUR_IS_POSITIONED;
574
pcur->old_stored = BTR_PCUR_OLD_NOT_STORED;
576
pcur->trx_if_known = NULL;
579
/**************************************************************************
580
Positions a cursor at a randomly chosen position within a B-tree. */
583
btr_pcur_open_at_rnd_pos(
584
/*=====================*/
585
dict_index_t* index, /* in: index */
586
ulint latch_mode, /* in: BTR_SEARCH_LEAF, ... */
587
btr_pcur_t* cursor, /* in/out: B-tree pcur */
588
mtr_t* mtr) /* in: mtr */
590
/* Initialize the cursor */
592
cursor->latch_mode = latch_mode;
593
cursor->search_mode = PAGE_CUR_G;
595
btr_pcur_init(cursor);
597
btr_cur_open_at_rnd_pos(index, latch_mode,
598
btr_pcur_get_btr_cur(cursor), mtr);
599
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
600
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
602
cursor->trx_if_known = NULL;
605
/******************************************************************
606
Frees the possible memory heap of a persistent cursor and sets the latch
607
mode of the persistent cursor to BTR_NO_LATCHES. */
612
btr_pcur_t* cursor) /* in: persistent cursor */
614
if (cursor->old_rec_buf != NULL) {
616
mem_free(cursor->old_rec_buf);
618
cursor->old_rec = NULL;
619
cursor->old_rec_buf = NULL;
622
cursor->btr_cur.page_cur.rec = NULL;
623
cursor->old_rec = NULL;
624
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
626
cursor->latch_mode = BTR_NO_LATCHES;
627
cursor->pos_state = BTR_PCUR_NOT_POSITIONED;
629
cursor->trx_if_known = NULL;