mySQL 5.0.11 sources for tomato
[tomato.git] / release / src / router / mysql / storage / innodb_plugin / include / btr0pcur.ic
blob70cd3fde48d205a9579ca50ac64db729fd80130a
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., 
15 51 Franklin 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, ... */
30 UNIV_INLINE
31 ulint
32 btr_pcur_get_rel_pos(
33 /*=================*/
34         const btr_pcur_t*       cursor) /*!< in: persistent cursor */
36         ut_ad(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. */
47 UNIV_INLINE
48 void
49 btr_pcur_set_mtr(
50 /*=============*/
51         btr_pcur_t*     cursor, /*!< in: persistent cursor */
52         mtr_t*          mtr)    /*!< in, own: mtr */
54         ut_ad(cursor);
56         cursor->mtr = mtr;
59 /*********************************************************//**
60 Gets the mtr field for a pcur.
61 @return mtr */
62 UNIV_INLINE
63 mtr_t*
64 btr_pcur_get_mtr(
65 /*=============*/
66         btr_pcur_t*     cursor) /*!< in: persistent cursor */
68         ut_ad(cursor);
70         return(cursor->mtr);
73 #ifdef UNIV_DEBUG
74 /*********************************************************//**
75 Returns the btr cursor component of a persistent cursor.
76 @return pointer to btr cursor component */
77 UNIV_INLINE
78 btr_cur_t*
79 btr_pcur_get_btr_cur(
80 /*=================*/
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 */
90 UNIV_INLINE
91 page_cur_t*
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 */
102 UNIV_INLINE
103 page_t*
104 btr_pcur_get_page(
105 /*==============*/
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 */
116 UNIV_INLINE
117 buf_block_t*
118 btr_pcur_get_block(
119 /*===============*/
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 */
130 UNIV_INLINE
131 rec_t*
132 btr_pcur_get_rec(
133 /*=============*/
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 */
146 UNIV_INLINE
147 ulint
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 */
168 UNIV_INLINE
169 ulint
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
187 a page. */
188 UNIV_INLINE
189 ibool
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
202 a page. */
203 UNIV_INLINE
204 ibool
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. */
217 UNIV_INLINE
218 ibool
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)) {
229                 return(FALSE);
230         }
232         return(TRUE);
235 /*********************************************************//**
236 Checks if the persistent cursor is before the first user record in
237 the index tree. */
238 UNIV_INLINE
239 ibool
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) {
250                 return(FALSE);
251         }
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
258 the index tree. */
259 UNIV_INLINE
260 ibool
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) {
271                 return(FALSE);
272         }
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. */
279 UNIV_INLINE
280 void
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. */
295 UNIV_INLINE
296 void
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. */
311 UNIV_INLINE
312 void
313 btr_pcur_move_to_last_on_page(
314 /*==========================*/
315         btr_pcur_t*     cursor, /*!< in: persistent cursor */
316         mtr_t*          mtr)    /*!< in: mtr */
318         UT_NOT_USED(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 */
331 UNIV_INLINE
332 ibool
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;
342 loop:
343         if (btr_pcur_is_after_last_on_page(cursor)) {
345                 if (btr_pcur_is_after_last_in_tree(cursor, mtr)) {
347                         return(FALSE);
348                 }
350                 btr_pcur_move_to_next_page(cursor, mtr);
351         } else {
352                 btr_pcur_move_to_next_on_page(cursor);
353         }
355         if (btr_pcur_is_on_user_rec(cursor)) {
357                 return(TRUE);
358         }
360         goto loop;
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 */
367 UNIV_INLINE
368 ibool
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)) {
384                         return(FALSE);
385                 }
387                 btr_pcur_move_to_next_page(cursor, mtr);
389                 return(TRUE);
390         }
392         btr_pcur_move_to_next_on_page(cursor);
394         return(TRUE);
397 /**************************************************************//**
398 Commits the mtr and sets the pcur latch mode to BTR_NO_LATCHES,
399 that is, the cursor becomes detached.
400 Function btr_pcur_store_position should be used before calling this,
401 if restoration of cursor is wanted later. */
402 UNIV_INLINE
403 void
404 btr_pcur_commit_specify_mtr(
405 /*========================*/
406         btr_pcur_t*     pcur,   /*!< in: persistent cursor */
407         mtr_t*          mtr)    /*!< in: mtr to commit */
409         ut_a(pcur->pos_state == BTR_PCUR_IS_POSITIONED);
411         pcur->latch_mode = BTR_NO_LATCHES;
413         mtr_commit(mtr);
415         pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
418 /**************************************************************//**
419 Sets the old_rec_buf field to NULL. */
420 UNIV_INLINE
421 void
422 btr_pcur_init(
423 /*==========*/
424         btr_pcur_t*     pcur)   /*!< in: persistent cursor */
426         pcur->old_stored = BTR_PCUR_OLD_NOT_STORED;
427         pcur->old_rec_buf = NULL;
428         pcur->old_rec = NULL;
431 /**************************************************************//**
432 Initializes and opens a persistent cursor to an index tree. It should be
433 closed with btr_pcur_close. */
434 UNIV_INLINE
435 void
436 btr_pcur_open_func(
437 /*===============*/
438         dict_index_t*   index,  /*!< in: index */
439         const dtuple_t* tuple,  /*!< in: tuple on which search done */
440         ulint           mode,   /*!< in: PAGE_CUR_L, ...;
441                                 NOTE that if the search is made using a unique
442                                 prefix of a record, mode should be
443                                 PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
444                                 may end up on the previous page from the
445                                 record! */
446         ulint           latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */
447         btr_pcur_t*     cursor, /*!< in: memory buffer for persistent cursor */
448         const char*     file,   /*!< in: file name */
449         ulint           line,   /*!< in: line where called */
450         mtr_t*          mtr)    /*!< in: mtr */
452         btr_cur_t*      btr_cursor;
454         /* Initialize the cursor */
456         btr_pcur_init(cursor);
458         cursor->latch_mode = latch_mode;
459         cursor->search_mode = mode;
461         /* Search with the tree cursor */
463         btr_cursor = btr_pcur_get_btr_cur(cursor);
465         btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode,
466                                     btr_cursor, 0, file, line, mtr);
467         cursor->pos_state = BTR_PCUR_IS_POSITIONED;
469         cursor->trx_if_known = NULL;
472 /**************************************************************//**
473 Opens an persistent cursor to an index tree without initializing the
474 cursor. */
475 UNIV_INLINE
476 void
477 btr_pcur_open_with_no_init_func(
478 /*============================*/
479         dict_index_t*   index,  /*!< in: index */
480         const dtuple_t* tuple,  /*!< in: tuple on which search done */
481         ulint           mode,   /*!< in: PAGE_CUR_L, ...;
482                                 NOTE that if the search is made using a unique
483                                 prefix of a record, mode should be
484                                 PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
485                                 may end up on the previous page of the
486                                 record! */
487         ulint           latch_mode,/*!< in: BTR_SEARCH_LEAF, ...;
488                                 NOTE that if has_search_latch != 0 then
489                                 we maybe do not acquire a latch on the cursor
490                                 page, but assume that the caller uses his
491                                 btr search latch to protect the record! */
492         btr_pcur_t*     cursor, /*!< in: memory buffer for persistent cursor */
493         ulint           has_search_latch,/*!< in: latch mode the caller
494                                 currently has on btr_search_latch:
495                                 RW_S_LATCH, or 0 */
496         const char*     file,   /*!< in: file name */
497         ulint           line,   /*!< in: line where called */
498         mtr_t*          mtr)    /*!< in: mtr */
500         btr_cur_t*      btr_cursor;
502         cursor->latch_mode = latch_mode;
503         cursor->search_mode = mode;
505         /* Search with the tree cursor */
507         btr_cursor = btr_pcur_get_btr_cur(cursor);
509         btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode,
510                                     btr_cursor, has_search_latch,
511                                     file, line, mtr);
512         cursor->pos_state = BTR_PCUR_IS_POSITIONED;
514         cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
516         cursor->trx_if_known = NULL;
519 /*****************************************************************//**
520 Opens a persistent cursor at either end of an index. */
521 UNIV_INLINE
522 void
523 btr_pcur_open_at_index_side(
524 /*========================*/
525         ibool           from_left,      /*!< in: TRUE if open to the low end,
526                                         FALSE if to the high end */
527         dict_index_t*   index,          /*!< in: index */
528         ulint           latch_mode,     /*!< in: latch mode */
529         btr_pcur_t*     pcur,           /*!< in: cursor */
530         ibool           do_init,        /*!< in: TRUE if should be initialized */
531         mtr_t*          mtr)            /*!< in: mtr */
533         pcur->latch_mode = latch_mode;
535         if (from_left) {
536                 pcur->search_mode = PAGE_CUR_G;
537         } else {
538                 pcur->search_mode = PAGE_CUR_L;
539         }
541         if (do_init) {
542                 btr_pcur_init(pcur);
543         }
545         btr_cur_open_at_index_side(from_left, index, latch_mode,
546                                    btr_pcur_get_btr_cur(pcur), mtr);
547         pcur->pos_state = BTR_PCUR_IS_POSITIONED;
549         pcur->old_stored = BTR_PCUR_OLD_NOT_STORED;
551         pcur->trx_if_known = NULL;
554 /**********************************************************************//**
555 Positions a cursor at a randomly chosen position within a B-tree. */
556 UNIV_INLINE
557 void
558 btr_pcur_open_at_rnd_pos_func(
559 /*==========================*/
560         dict_index_t*   index,          /*!< in: index */
561         ulint           latch_mode,     /*!< in: BTR_SEARCH_LEAF, ... */
562         btr_pcur_t*     cursor,         /*!< in/out: B-tree pcur */
563         const char*     file,           /*!< in: file name */
564         ulint           line,           /*!< in: line where called */
565         mtr_t*          mtr)            /*!< in: mtr */
567         /* Initialize the cursor */
569         cursor->latch_mode = latch_mode;
570         cursor->search_mode = PAGE_CUR_G;
572         btr_pcur_init(cursor);
574         btr_cur_open_at_rnd_pos_func(index, latch_mode,
575                                      btr_pcur_get_btr_cur(cursor),
576                                      file, line, mtr);
577         cursor->pos_state = BTR_PCUR_IS_POSITIONED;
578         cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
580         cursor->trx_if_known = NULL;
583 /**************************************************************//**
584 Frees the possible memory heap of a persistent cursor and sets the latch
585 mode of the persistent cursor to BTR_NO_LATCHES. */
586 UNIV_INLINE
587 void
588 btr_pcur_close(
589 /*===========*/
590         btr_pcur_t*     cursor) /*!< in: persistent cursor */
592         if (cursor->old_rec_buf != NULL) {
594                 mem_free(cursor->old_rec_buf);
596                 cursor->old_rec = NULL;
597                 cursor->old_rec_buf = NULL;
598         }
600         cursor->btr_cur.page_cur.rec = NULL;
601         cursor->btr_cur.page_cur.block = NULL;
602         cursor->old_rec = NULL;
603         cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
605         cursor->latch_mode = BTR_NO_LATCHES;
606         cursor->pos_state = BTR_PCUR_NOT_POSITIONED;
608         cursor->trx_if_known = NULL;