~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/btr/btr0pcur.cc

  • Committer: Mark Atwood
  • Date: 2008-10-03 01:39:40 UTC
  • mto: This revision was merged to the branch mainline in revision 437.
  • Revision ID: mark@fallenpegasus.com-20081003013940-mvefjo725dltz41h
rename logging_noop to logging_query

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*****************************************************************************
2
 
 
3
 
Copyright (C) 1996, 2010, Innobase Oy. All Rights Reserved.
4
 
 
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.
8
 
 
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.
12
 
 
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
16
 
 
17
 
*****************************************************************************/
18
 
 
19
 
/**************************************************//**
20
 
@file btr/btr0pcur.c
21
 
The index tree persistent cursor
22
 
 
23
 
Created 2/23/1996 Heikki Tuuri
24
 
*******************************************************/
25
 
 
26
 
#include "btr0pcur.h"
27
 
 
28
 
#ifdef UNIV_NONINL
29
 
#include "btr0pcur.ic"
30
 
#endif
31
 
 
32
 
#include "ut0byte.h"
33
 
#include "rem0cmp.h"
34
 
#include "trx0trx.h"
35
 
 
36
 
/**************************************************************//**
37
 
Allocates memory for a persistent cursor object and initializes the cursor.
38
 
@return own: persistent cursor */
39
 
UNIV_INTERN
40
 
btr_pcur_t*
41
 
btr_pcur_create_for_mysql(void)
42
 
/*============================*/
43
 
{
44
 
        btr_pcur_t*     pcur;
45
 
 
46
 
        pcur = (btr_pcur_t *)mem_alloc(sizeof(btr_pcur_t));
47
 
 
48
 
        pcur->btr_cur.index = NULL;
49
 
        btr_pcur_init(pcur);
50
 
 
51
 
        return(pcur);
52
 
}
53
 
 
54
 
/**************************************************************//**
55
 
Frees the memory for a persistent cursor object. */
56
 
UNIV_INTERN
57
 
void
58
 
btr_pcur_free_for_mysql(
59
 
/*====================*/
60
 
        btr_pcur_t*     cursor) /*!< in, own: persistent cursor */
61
 
{
62
 
        if (cursor->old_rec_buf != NULL) {
63
 
 
64
 
                mem_free(cursor->old_rec_buf);
65
 
 
66
 
                cursor->old_rec_buf = NULL;
67
 
        }
68
 
 
69
 
        cursor->btr_cur.page_cur.rec = NULL;
70
 
        cursor->old_rec = NULL;
71
 
        cursor->old_n_fields = 0;
72
 
        cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
73
 
 
74
 
        cursor->latch_mode = BTR_NO_LATCHES;
75
 
        cursor->pos_state = BTR_PCUR_NOT_POSITIONED;
76
 
 
77
 
        mem_free(cursor);
78
 
}
79
 
 
80
 
/**************************************************************//**
81
 
The position of the cursor is stored by taking an initial segment of the
82
 
record the cursor is positioned on, before, or after, and copying it to the
83
 
cursor data structure, or just setting a flag if the cursor id before the
84
 
first in an EMPTY tree, or after the last in an EMPTY tree. NOTE that the
85
 
page where the cursor is positioned must not be empty if the index tree is
86
 
not totally empty! */
87
 
UNIV_INTERN
88
 
void
89
 
btr_pcur_store_position(
90
 
/*====================*/
91
 
        btr_pcur_t*     cursor, /*!< in: persistent cursor */
92
 
        mtr_t*          mtr)    /*!< in: mtr */
93
 
{
94
 
        page_cur_t*     page_cursor;
95
 
        buf_block_t*    block;
96
 
        rec_t*          rec;
97
 
        dict_index_t*   index;
98
 
        page_t*         page;
99
 
        ulint           offs;
100
 
 
101
 
        ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
102
 
        ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
103
 
 
104
 
        block = btr_pcur_get_block(cursor);
105
 
        index = btr_cur_get_index(btr_pcur_get_btr_cur(cursor));
106
 
 
107
 
        page_cursor = btr_pcur_get_page_cur(cursor);
108
 
 
109
 
        rec = page_cur_get_rec(page_cursor);
110
 
        page = page_align(rec);
111
 
        offs = page_offset(rec);
112
 
 
113
 
        ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_S_FIX)
114
 
              || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
115
 
        ut_a(cursor->latch_mode != BTR_NO_LATCHES);
116
 
 
117
 
        if (UNIV_UNLIKELY(page_get_n_recs(page) == 0)) {
118
 
                /* It must be an empty index tree; NOTE that in this case
119
 
                we do not store the modify_clock, but always do a search
120
 
                if we restore the cursor position */
121
 
 
122
 
                ut_a(btr_page_get_next(page, mtr) == FIL_NULL);
123
 
                ut_a(btr_page_get_prev(page, mtr) == FIL_NULL);
124
 
 
125
 
                cursor->old_stored = BTR_PCUR_OLD_STORED;
126
 
 
127
 
                if (page_rec_is_supremum_low(offs)) {
128
 
 
129
 
                        cursor->rel_pos = BTR_PCUR_AFTER_LAST_IN_TREE;
130
 
                } else {
131
 
                        cursor->rel_pos = BTR_PCUR_BEFORE_FIRST_IN_TREE;
132
 
                }
133
 
 
134
 
                return;
135
 
        }
136
 
 
137
 
        if (page_rec_is_supremum_low(offs)) {
138
 
 
139
 
                rec = page_rec_get_prev(rec);
140
 
 
141
 
                cursor->rel_pos = BTR_PCUR_AFTER;
142
 
 
143
 
        } else if (page_rec_is_infimum_low(offs)) {
144
 
 
145
 
                rec = page_rec_get_next(rec);
146
 
 
147
 
                cursor->rel_pos = BTR_PCUR_BEFORE;
148
 
        } else {
149
 
                cursor->rel_pos = BTR_PCUR_ON;
150
 
        }
151
 
 
152
 
        cursor->old_stored = BTR_PCUR_OLD_STORED;
153
 
        cursor->old_rec = dict_index_copy_rec_order_prefix(
154
 
                index, rec, &cursor->old_n_fields,
155
 
                &cursor->old_rec_buf, &cursor->buf_size);
156
 
 
157
 
        cursor->block_when_stored = block;
158
 
        cursor->modify_clock = buf_block_get_modify_clock(block);
159
 
}
160
 
 
161
 
/**************************************************************//**
162
 
Copies the stored position of a pcur to another pcur. */
163
 
UNIV_INTERN
164
 
void
165
 
btr_pcur_copy_stored_position(
166
 
/*==========================*/
167
 
        btr_pcur_t*     pcur_receive,   /*!< in: pcur which will receive the
168
 
                                        position info */
169
 
        btr_pcur_t*     pcur_donate)    /*!< in: pcur from which the info is
170
 
                                        copied */
171
 
{
172
 
        if (pcur_receive->old_rec_buf) {
173
 
                mem_free(pcur_receive->old_rec_buf);
174
 
        }
175
 
 
176
 
        ut_memcpy(pcur_receive, pcur_donate, sizeof(btr_pcur_t));
177
 
 
178
 
        if (pcur_donate->old_rec_buf) {
179
 
 
180
 
                pcur_receive->old_rec_buf = (unsigned char *)mem_alloc(pcur_donate->buf_size);
181
 
 
182
 
                ut_memcpy(pcur_receive->old_rec_buf, pcur_donate->old_rec_buf,
183
 
                          pcur_donate->buf_size);
184
 
                pcur_receive->old_rec = pcur_receive->old_rec_buf
185
 
                        + (pcur_donate->old_rec - pcur_donate->old_rec_buf);
186
 
        }
187
 
 
188
 
        pcur_receive->old_n_fields = pcur_donate->old_n_fields;
189
 
}
190
 
 
191
 
/**************************************************************//**
192
 
Restores the stored position of a persistent cursor bufferfixing the page and
193
 
obtaining the specified latches. If the cursor position was saved when the
194
 
(1) cursor was positioned on a user record: this function restores the position
195
 
to the last record LESS OR EQUAL to the stored record;
196
 
(2) cursor was positioned on a page infimum record: restores the position to
197
 
the last record LESS than the user record which was the successor of the page
198
 
infimum;
199
 
(3) cursor was positioned on the page supremum: restores to the first record
200
 
GREATER than the user record which was the predecessor of the supremum.
201
 
(4) cursor was positioned before the first or after the last in an empty tree:
202
 
restores to before first or after the last in the tree.
203
 
@return TRUE if the cursor position was stored when it was on a user
204
 
record and it can be restored on a user record whose ordering fields
205
 
are identical to the ones of the original user record */
206
 
UNIV_INTERN
207
 
ibool
208
 
btr_pcur_restore_position_func(
209
 
/*===========================*/
210
 
        ulint           latch_mode,     /*!< in: BTR_SEARCH_LEAF, ... */
211
 
        btr_pcur_t*     cursor,         /*!< in: detached persistent cursor */
212
 
        const char*     file,           /*!< in: file name */
213
 
        ulint           line,           /*!< in: line where called */
214
 
        mtr_t*          mtr)            /*!< in: mtr */
215
 
{
216
 
        dict_index_t*   index;
217
 
        dtuple_t*       tuple;
218
 
        ulint           mode;
219
 
        ulint           old_mode;
220
 
        mem_heap_t*     heap;
221
 
 
222
 
        ut_ad(mtr);
223
 
        ut_ad(mtr->state == MTR_ACTIVE);
224
 
 
225
 
        index = btr_cur_get_index(btr_pcur_get_btr_cur(cursor));
226
 
 
227
 
        if (UNIV_UNLIKELY(cursor->old_stored != BTR_PCUR_OLD_STORED)
228
 
            || UNIV_UNLIKELY(cursor->pos_state != BTR_PCUR_WAS_POSITIONED
229
 
                             && cursor->pos_state != BTR_PCUR_IS_POSITIONED)) {
230
 
                ut_print_buf(stderr, cursor, sizeof(btr_pcur_t));
231
 
                putc('\n', stderr);
232
 
                if (cursor->trx_if_known) {
233
 
                        trx_print(stderr, cursor->trx_if_known, 0);
234
 
                }
235
 
 
236
 
                ut_error;
237
 
        }
238
 
 
239
 
        if (UNIV_UNLIKELY
240
 
            (cursor->rel_pos == BTR_PCUR_AFTER_LAST_IN_TREE
241
 
             || cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE)) {
242
 
 
243
 
                /* In these cases we do not try an optimistic restoration,
244
 
                but always do a search */
245
 
 
246
 
                btr_cur_open_at_index_side(
247
 
                        cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE,
248
 
                        index, latch_mode, btr_pcur_get_btr_cur(cursor), mtr);
249
 
 
250
 
                cursor->block_when_stored = btr_pcur_get_block(cursor);
251
 
 
252
 
                return(FALSE);
253
 
        }
254
 
 
255
 
        ut_a(cursor->old_rec);
256
 
        ut_a(cursor->old_n_fields);
257
 
 
258
 
        if (UNIV_LIKELY(latch_mode == BTR_SEARCH_LEAF)
259
 
            || UNIV_LIKELY(latch_mode == BTR_MODIFY_LEAF)) {
260
 
                /* Try optimistic restoration */
261
 
 
262
 
                if (UNIV_LIKELY(buf_page_optimistic_get(
263
 
                                        latch_mode,
264
 
                                        cursor->block_when_stored,
265
 
                                        cursor->modify_clock,
266
 
                                        file, line, mtr))) {
267
 
                        cursor->pos_state = BTR_PCUR_IS_POSITIONED;
268
 
 
269
 
                        buf_block_dbg_add_level(btr_pcur_get_block(cursor),
270
 
                                                SYNC_TREE_NODE);
271
 
 
272
 
                        if (cursor->rel_pos == BTR_PCUR_ON) {
273
 
#ifdef UNIV_DEBUG
274
 
                                const rec_t*    rec;
275
 
                                const ulint*    offsets1;
276
 
                                const ulint*    offsets2;
277
 
#endif /* UNIV_DEBUG */
278
 
                                cursor->latch_mode = latch_mode;
279
 
#ifdef UNIV_DEBUG
280
 
                                rec = btr_pcur_get_rec(cursor);
281
 
 
282
 
                                heap = mem_heap_create(256);
283
 
                                offsets1 = rec_get_offsets(
284
 
                                        cursor->old_rec, index, NULL,
285
 
                                        cursor->old_n_fields, &heap);
286
 
                                offsets2 = rec_get_offsets(
287
 
                                        rec, index, NULL,
288
 
                                        cursor->old_n_fields, &heap);
289
 
 
290
 
                                ut_ad(!cmp_rec_rec(cursor->old_rec,
291
 
                                                   rec, offsets1, offsets2,
292
 
                                                   index));
293
 
                                mem_heap_free(heap);
294
 
#endif /* UNIV_DEBUG */
295
 
                                return(TRUE);
296
 
                        }
297
 
 
298
 
                        return(FALSE);
299
 
                }
300
 
        }
301
 
 
302
 
        /* If optimistic restoration did not succeed, open the cursor anew */
303
 
 
304
 
        heap = mem_heap_create(256);
305
 
 
306
 
        tuple = dict_index_build_data_tuple(index, cursor->old_rec,
307
 
                                            cursor->old_n_fields, heap);
308
 
 
309
 
        /* Save the old search mode of the cursor */
310
 
        old_mode = cursor->search_mode;
311
 
 
312
 
        if (UNIV_LIKELY(cursor->rel_pos == BTR_PCUR_ON)) {
313
 
                mode = PAGE_CUR_LE;
314
 
        } else if (cursor->rel_pos == BTR_PCUR_AFTER) {
315
 
                mode = PAGE_CUR_G;
316
 
        } else {
317
 
                ut_ad(cursor->rel_pos == BTR_PCUR_BEFORE);
318
 
                mode = PAGE_CUR_L;
319
 
        }
320
 
 
321
 
        btr_pcur_open_with_no_init_func(index, tuple, mode, latch_mode,
322
 
                                        cursor, 0, file, line, mtr);
323
 
 
324
 
        /* Restore the old search mode */
325
 
        cursor->search_mode = old_mode;
326
 
 
327
 
        if (cursor->rel_pos == BTR_PCUR_ON
328
 
            && btr_pcur_is_on_user_rec(cursor)
329
 
            && 0 == cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor),
330
 
                                   rec_get_offsets(
331
 
                                           btr_pcur_get_rec(cursor), index,
332
 
                                           NULL, ULINT_UNDEFINED, &heap))) {
333
 
 
334
 
                /* We have to store the NEW value for the modify clock, since
335
 
                the cursor can now be on a different page! But we can retain
336
 
                the value of old_rec */
337
 
 
338
 
                cursor->block_when_stored = btr_pcur_get_block(cursor);
339
 
                cursor->modify_clock = buf_block_get_modify_clock(
340
 
                        cursor->block_when_stored);
341
 
                cursor->old_stored = BTR_PCUR_OLD_STORED;
342
 
 
343
 
                mem_heap_free(heap);
344
 
 
345
 
                return(TRUE);
346
 
        }
347
 
 
348
 
        mem_heap_free(heap);
349
 
 
350
 
        /* We have to store new position information, modify_clock etc.,
351
 
        to the cursor because it can now be on a different page, the record
352
 
        under it may have been removed, etc. */
353
 
 
354
 
        btr_pcur_store_position(cursor, mtr);
355
 
 
356
 
        return(FALSE);
357
 
}
358
 
 
359
 
/**************************************************************//**
360
 
If the latch mode of the cursor is BTR_LEAF_SEARCH or BTR_LEAF_MODIFY,
361
 
releases the page latch and bufferfix reserved by the cursor.
362
 
NOTE! In the case of BTR_LEAF_MODIFY, there should not exist changes
363
 
made by the current mini-transaction to the data protected by the
364
 
cursor latch, as then the latch must not be released until mtr_commit. */
365
 
UNIV_INTERN
366
 
void
367
 
btr_pcur_release_leaf(
368
 
/*==================*/
369
 
        btr_pcur_t*     cursor, /*!< in: persistent cursor */
370
 
        mtr_t*          mtr)    /*!< in: mtr */
371
 
{
372
 
        buf_block_t*    block;
373
 
 
374
 
        ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
375
 
        ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
376
 
 
377
 
        block = btr_pcur_get_block(cursor);
378
 
 
379
 
        btr_leaf_page_release(block, cursor->latch_mode, mtr);
380
 
 
381
 
        cursor->latch_mode = BTR_NO_LATCHES;
382
 
 
383
 
        cursor->pos_state = BTR_PCUR_WAS_POSITIONED;
384
 
}
385
 
 
386
 
/*********************************************************//**
387
 
Moves the persistent cursor to the first record on the next page. Releases the
388
 
latch on the current page, and bufferunfixes it. Note that there must not be
389
 
modifications on the current page, as then the x-latch can be released only in
390
 
mtr_commit. */
391
 
UNIV_INTERN
392
 
void
393
 
btr_pcur_move_to_next_page(
394
 
/*=======================*/
395
 
        btr_pcur_t*     cursor, /*!< in: persistent cursor; must be on the
396
 
                                last record of the current page */
397
 
        mtr_t*          mtr)    /*!< in: mtr */
398
 
{
399
 
        ulint           next_page_no;
400
 
        ulint           space;
401
 
        ulint           zip_size;
402
 
        page_t*         page;
403
 
        buf_block_t*    next_block;
404
 
        page_t*         next_page;
405
 
 
406
 
        ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
407
 
        ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
408
 
        ut_ad(btr_pcur_is_after_last_on_page(cursor));
409
 
 
410
 
        cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
411
 
 
412
 
        page = btr_pcur_get_page(cursor);
413
 
        next_page_no = btr_page_get_next(page, mtr);
414
 
        space = buf_block_get_space(btr_pcur_get_block(cursor));
415
 
        zip_size = buf_block_get_zip_size(btr_pcur_get_block(cursor));
416
 
 
417
 
        ut_ad(next_page_no != FIL_NULL);
418
 
 
419
 
        next_block = btr_block_get(space, zip_size, next_page_no,
420
 
                                   cursor->latch_mode, mtr);
421
 
        next_page = buf_block_get_frame(next_block);
422
 
#ifdef UNIV_BTR_DEBUG
423
 
        ut_a(page_is_comp(next_page) == page_is_comp(page));
424
 
        ut_a(btr_page_get_prev(next_page, mtr)
425
 
             == buf_block_get_page_no(btr_pcur_get_block(cursor)));
426
 
#endif /* UNIV_BTR_DEBUG */
427
 
        next_block->check_index_page_at_flush = TRUE;
428
 
 
429
 
        btr_leaf_page_release(btr_pcur_get_block(cursor),
430
 
                              cursor->latch_mode, mtr);
431
 
 
432
 
        page_cur_set_before_first(next_block, btr_pcur_get_page_cur(cursor));
433
 
 
434
 
        page_check_dir(next_page);
435
 
}
436
 
 
437
 
/*********************************************************//**
438
 
Moves the persistent cursor backward if it is on the first record of the page.
439
 
Commits mtr. Note that to prevent a possible deadlock, the operation
440
 
first stores the position of the cursor, commits mtr, acquires the necessary
441
 
latches and restores the cursor position again before returning. The
442
 
alphabetical position of the cursor is guaranteed to be sensible on
443
 
return, but it may happen that the cursor is not positioned on the last
444
 
record of any page, because the structure of the tree may have changed
445
 
during the time when the cursor had no latches. */
446
 
UNIV_INTERN
447
 
void
448
 
btr_pcur_move_backward_from_page(
449
 
/*=============================*/
450
 
        btr_pcur_t*     cursor, /*!< in: persistent cursor, must be on the first
451
 
                                record of the current page */
452
 
        mtr_t*          mtr)    /*!< in: mtr */
453
 
{
454
 
        ulint           prev_page_no;
455
 
        page_t*         page;
456
 
        buf_block_t*    prev_block;
457
 
        ulint           latch_mode;
458
 
        ulint           latch_mode2;
459
 
 
460
 
        ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
461
 
        ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
462
 
        ut_ad(btr_pcur_is_before_first_on_page(cursor));
463
 
        ut_ad(!btr_pcur_is_before_first_in_tree(cursor, mtr));
464
 
 
465
 
        latch_mode = cursor->latch_mode;
466
 
 
467
 
        if (latch_mode == BTR_SEARCH_LEAF) {
468
 
 
469
 
                latch_mode2 = BTR_SEARCH_PREV;
470
 
 
471
 
        } else if (latch_mode == BTR_MODIFY_LEAF) {
472
 
 
473
 
                latch_mode2 = BTR_MODIFY_PREV;
474
 
        } else {
475
 
                latch_mode2 = 0; /* To eliminate compiler warning */
476
 
                ut_error;
477
 
        }
478
 
 
479
 
        btr_pcur_store_position(cursor, mtr);
480
 
 
481
 
        mtr_commit(mtr);
482
 
 
483
 
        mtr_start(mtr);
484
 
 
485
 
        btr_pcur_restore_position(latch_mode2, cursor, mtr);
486
 
 
487
 
        page = btr_pcur_get_page(cursor);
488
 
 
489
 
        prev_page_no = btr_page_get_prev(page, mtr);
490
 
 
491
 
        if (prev_page_no == FIL_NULL) {
492
 
        } else if (btr_pcur_is_before_first_on_page(cursor)) {
493
 
 
494
 
                prev_block = btr_pcur_get_btr_cur(cursor)->left_block;
495
 
 
496
 
                btr_leaf_page_release(btr_pcur_get_block(cursor),
497
 
                                      latch_mode, mtr);
498
 
 
499
 
                page_cur_set_after_last(prev_block,
500
 
                                        btr_pcur_get_page_cur(cursor));
501
 
        } else {
502
 
 
503
 
                /* The repositioned cursor did not end on an infimum record on
504
 
                a page. Cursor repositioning acquired a latch also on the
505
 
                previous page, but we do not need the latch: release it. */
506
 
 
507
 
                prev_block = btr_pcur_get_btr_cur(cursor)->left_block;
508
 
 
509
 
                btr_leaf_page_release(prev_block, latch_mode, mtr);
510
 
        }
511
 
 
512
 
        cursor->latch_mode = latch_mode;
513
 
 
514
 
        cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
515
 
}
516
 
 
517
 
/*********************************************************//**
518
 
Moves the persistent cursor to the previous record in the tree. If no records
519
 
are left, the cursor stays 'before first in tree'.
520
 
@return TRUE if the cursor was not before first in tree */
521
 
UNIV_INTERN
522
 
ibool
523
 
btr_pcur_move_to_prev(
524
 
/*==================*/
525
 
        btr_pcur_t*     cursor, /*!< in: persistent cursor; NOTE that the
526
 
                                function may release the page latch */
527
 
        mtr_t*          mtr)    /*!< in: mtr */
528
 
{
529
 
        ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
530
 
        ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
531
 
 
532
 
        cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
533
 
 
534
 
        if (btr_pcur_is_before_first_on_page(cursor)) {
535
 
 
536
 
                if (btr_pcur_is_before_first_in_tree(cursor, mtr)) {
537
 
 
538
 
                        return(FALSE);
539
 
                }
540
 
 
541
 
                btr_pcur_move_backward_from_page(cursor, mtr);
542
 
 
543
 
                return(TRUE);
544
 
        }
545
 
 
546
 
        btr_pcur_move_to_prev_on_page(cursor);
547
 
 
548
 
        return(TRUE);
549
 
}
550
 
 
551
 
/**************************************************************//**
552
 
If mode is PAGE_CUR_G or PAGE_CUR_GE, opens a persistent cursor on the first
553
 
user record satisfying the search condition, in the case PAGE_CUR_L or
554
 
PAGE_CUR_LE, on the last user record. If no such user record exists, then
555
 
in the first case sets the cursor after last in tree, and in the latter case
556
 
before first in tree. The latching mode must be BTR_SEARCH_LEAF or
557
 
BTR_MODIFY_LEAF. */
558
 
UNIV_INTERN
559
 
void
560
 
btr_pcur_open_on_user_rec_func(
561
 
/*===========================*/
562
 
        dict_index_t*   index,          /*!< in: index */
563
 
        const dtuple_t* tuple,          /*!< in: tuple on which search done */
564
 
        ulint           mode,           /*!< in: PAGE_CUR_L, ... */
565
 
        ulint           latch_mode,     /*!< in: BTR_SEARCH_LEAF or
566
 
                                        BTR_MODIFY_LEAF */
567
 
        btr_pcur_t*     cursor,         /*!< in: memory buffer for persistent
568
 
                                        cursor */
569
 
        const char*     file,           /*!< in: file name */
570
 
        ulint           line,           /*!< in: line where called */
571
 
        mtr_t*          mtr)            /*!< in: mtr */
572
 
{
573
 
        btr_pcur_open_func(index, tuple, mode, latch_mode, cursor,
574
 
                           file, line, mtr);
575
 
 
576
 
        if ((mode == PAGE_CUR_GE) || (mode == PAGE_CUR_G)) {
577
 
 
578
 
                if (btr_pcur_is_after_last_on_page(cursor)) {
579
 
 
580
 
                        btr_pcur_move_to_next_user_rec(cursor, mtr);
581
 
                }
582
 
        } else {
583
 
                ut_ad((mode == PAGE_CUR_LE) || (mode == PAGE_CUR_L));
584
 
 
585
 
                /* Not implemented yet */
586
 
 
587
 
                ut_error;
588
 
        }
589
 
}