1
/*****************************************************************************
3
Copyright (C) 1996, 2010, 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., 51 Franklin
15
St, Fifth Floor, Boston, MA 02110-1301 USA
17
*****************************************************************************/
19
/**************************************************//**
20
@file include/btr0pcur.h
21
The index tree persistent cursor
23
Created 2/23/1996 Heikki Tuuri
24
*******************************************************/
30
#include "dict0dict.h"
31
#include "data0data.h"
36
#include "btr0types.h"
38
/* Relative positions for a stored cursor position */
40
#define BTR_PCUR_BEFORE 2
41
#define BTR_PCUR_AFTER 3
42
/* Note that if the tree is not empty, btr_pcur_store_position does not
43
use the following, but only uses the above three alternatives, where the
44
position is stored relative to a specific record: this makes implementation
45
of a scroll cursor easier */
46
#define BTR_PCUR_BEFORE_FIRST_IN_TREE 4 /* in an empty tree */
47
#define BTR_PCUR_AFTER_LAST_IN_TREE 5 /* in an empty tree */
49
/**************************************************************//**
50
Allocates memory for a persistent cursor object and initializes the cursor.
51
@return own: persistent cursor */
54
btr_pcur_create_for_mysql(void);
55
/*============================*/
56
/**************************************************************//**
57
Frees the memory for a persistent cursor object. */
60
btr_pcur_free_for_mysql(
61
/*====================*/
62
btr_pcur_t* cursor); /*!< in, own: persistent cursor */
63
/**************************************************************//**
64
Copies the stored position of a pcur to another pcur. */
67
btr_pcur_copy_stored_position(
68
/*==========================*/
69
btr_pcur_t* pcur_receive, /*!< in: pcur which will receive the
71
btr_pcur_t* pcur_donate); /*!< in: pcur from which the info is
73
/**************************************************************//**
74
Sets the old_rec_buf field to NULL. */
79
btr_pcur_t* pcur); /*!< in: persistent cursor */
80
/**************************************************************//**
81
Initializes and opens a persistent cursor to an index tree. It should be
82
closed with btr_pcur_close. */
87
dict_index_t* index, /*!< in: index */
88
const dtuple_t* tuple, /*!< in: tuple on which search done */
89
ulint mode, /*!< in: PAGE_CUR_L, ...;
90
NOTE that if the search is made using a unique
91
prefix of a record, mode should be
92
PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
93
may end up on the previous page from the
95
ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */
96
btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
97
const char* file, /*!< in: file name */
98
ulint line, /*!< in: line where called */
99
mtr_t* mtr); /*!< in: mtr */
100
#define btr_pcur_open(i,t,md,l,c,m) \
101
btr_pcur_open_func(i,t,md,l,c,__FILE__,__LINE__,m)
102
/**************************************************************//**
103
Opens an persistent cursor to an index tree without initializing the
107
btr_pcur_open_with_no_init_func(
108
/*============================*/
109
dict_index_t* index, /*!< in: index */
110
const dtuple_t* tuple, /*!< in: tuple on which search done */
111
ulint mode, /*!< in: PAGE_CUR_L, ...;
112
NOTE that if the search is made using a unique
113
prefix of a record, mode should be
114
PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
115
may end up on the previous page of the
117
ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ...;
118
NOTE that if has_search_latch != 0 then
119
we maybe do not acquire a latch on the cursor
120
page, but assume that the caller uses his
121
btr search latch to protect the record! */
122
btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
123
ulint has_search_latch,/*!< in: latch mode the caller
124
currently has on btr_search_latch:
126
const char* file, /*!< in: file name */
127
ulint line, /*!< in: line where called */
128
mtr_t* mtr); /*!< in: mtr */
129
#define btr_pcur_open_with_no_init(ix,t,md,l,cur,has,m) \
130
btr_pcur_open_with_no_init_func(ix,t,md,l,cur,has,__FILE__,__LINE__,m)
132
/*****************************************************************//**
133
Opens a persistent cursor at either end of an index. */
136
btr_pcur_open_at_index_side(
137
/*========================*/
138
ibool from_left, /*!< in: TRUE if open to the low end,
139
FALSE if to the high end */
140
dict_index_t* index, /*!< in: index */
141
ulint latch_mode, /*!< in: latch mode */
142
btr_pcur_t* pcur, /*!< in: cursor */
143
ibool do_init, /*!< in: TRUE if should be initialized */
144
mtr_t* mtr); /*!< in: mtr */
145
/**************************************************************//**
146
Gets the up_match value for a pcur after a search.
147
@return number of matched fields at the cursor or to the right if
148
search mode was PAGE_CUR_GE, otherwise undefined */
151
btr_pcur_get_up_match(
152
/*==================*/
153
btr_pcur_t* cursor); /*!< in: memory buffer for persistent cursor */
154
/**************************************************************//**
155
Gets the low_match value for a pcur after a search.
156
@return number of matched fields at the cursor or to the right if
157
search mode was PAGE_CUR_LE, otherwise undefined */
160
btr_pcur_get_low_match(
161
/*===================*/
162
btr_pcur_t* cursor); /*!< in: memory buffer for persistent cursor */
163
/**************************************************************//**
164
If mode is PAGE_CUR_G or PAGE_CUR_GE, opens a persistent cursor on the first
165
user record satisfying the search condition, in the case PAGE_CUR_L or
166
PAGE_CUR_LE, on the last user record. If no such user record exists, then
167
in the first case sets the cursor after last in tree, and in the latter case
168
before first in tree. The latching mode must be BTR_SEARCH_LEAF or
172
btr_pcur_open_on_user_rec_func(
173
/*===========================*/
174
dict_index_t* index, /*!< in: index */
175
const dtuple_t* tuple, /*!< in: tuple on which search done */
176
ulint mode, /*!< in: PAGE_CUR_L, ... */
177
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF or
179
btr_pcur_t* cursor, /*!< in: memory buffer for persistent
181
const char* file, /*!< in: file name */
182
ulint line, /*!< in: line where called */
183
mtr_t* mtr); /*!< in: mtr */
184
#define btr_pcur_open_on_user_rec(i,t,md,l,c,m) \
185
btr_pcur_open_on_user_rec_func(i,t,md,l,c,__FILE__,__LINE__,m)
186
/**********************************************************************//**
187
Positions a cursor at a randomly chosen position within a B-tree. */
190
btr_pcur_open_at_rnd_pos_func(
191
/*==========================*/
192
dict_index_t* index, /*!< in: index */
193
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */
194
btr_pcur_t* cursor, /*!< in/out: B-tree pcur */
195
const char* file, /*!< in: file name */
196
ulint line, /*!< in: line where called */
197
mtr_t* mtr); /*!< in: mtr */
198
#define btr_pcur_open_at_rnd_pos(i,l,c,m) \
199
btr_pcur_open_at_rnd_pos_func(i,l,c,__FILE__,__LINE__,m)
200
/**************************************************************//**
201
Frees the possible old_rec_buf buffer of a persistent cursor and sets the
202
latch mode of the persistent cursor to BTR_NO_LATCHES. */
207
btr_pcur_t* cursor); /*!< in: persistent cursor */
208
/**************************************************************//**
209
The position of the cursor is stored by taking an initial segment of the
210
record the cursor is positioned on, before, or after, and copying it to the
211
cursor data structure, or just setting a flag if the cursor id before the
212
first in an EMPTY tree, or after the last in an EMPTY tree. NOTE that the
213
page where the cursor is positioned must not be empty if the index tree is
214
not totally empty! */
217
btr_pcur_store_position(
218
/*====================*/
219
btr_pcur_t* cursor, /*!< in: persistent cursor */
220
mtr_t* mtr); /*!< in: mtr */
221
/**************************************************************//**
222
Restores the stored position of a persistent cursor bufferfixing the page and
223
obtaining the specified latches. If the cursor position was saved when the
224
(1) cursor was positioned on a user record: this function restores the position
225
to the last record LESS OR EQUAL to the stored record;
226
(2) cursor was positioned on a page infimum record: restores the position to
227
the last record LESS than the user record which was the successor of the page
229
(3) cursor was positioned on the page supremum: restores to the first record
230
GREATER than the user record which was the predecessor of the supremum.
231
(4) cursor was positioned before the first or after the last in an empty tree:
232
restores to before first or after the last in the tree.
233
@return TRUE if the cursor position was stored when it was on a user
234
record and it can be restored on a user record whose ordering fields
235
are identical to the ones of the original user record */
238
btr_pcur_restore_position_func(
239
/*===========================*/
240
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */
241
btr_pcur_t* cursor, /*!< in: detached persistent cursor */
242
const char* file, /*!< in: file name */
243
ulint line, /*!< in: line where called */
244
mtr_t* mtr); /*!< in: mtr */
245
#define btr_pcur_restore_position(l,cur,mtr) \
246
btr_pcur_restore_position_func(l,cur,__FILE__,__LINE__,mtr)
247
/**************************************************************//**
248
If the latch mode of the cursor is BTR_LEAF_SEARCH or BTR_LEAF_MODIFY,
249
releases the page latch and bufferfix reserved by the cursor.
250
NOTE! In the case of BTR_LEAF_MODIFY, there should not exist changes
251
made by the current mini-transaction to the data protected by the
252
cursor latch, as then the latch must not be released until mtr_commit. */
255
btr_pcur_release_leaf(
256
/*==================*/
257
btr_pcur_t* cursor, /*!< in: persistent cursor */
258
mtr_t* mtr); /*!< in: mtr */
259
/*********************************************************//**
260
Gets the rel_pos field for a cursor whose position has been stored.
261
@return BTR_PCUR_ON, ... */
264
btr_pcur_get_rel_pos(
265
/*=================*/
266
const btr_pcur_t* cursor);/*!< in: persistent cursor */
267
/*********************************************************//**
268
Sets the mtr field for a pcur. */
273
btr_pcur_t* cursor, /*!< in: persistent cursor */
274
mtr_t* mtr); /*!< in, own: mtr */
275
/*********************************************************//**
276
Gets the mtr field for a pcur.
282
btr_pcur_t* cursor); /*!< in: persistent cursor */
283
/**************************************************************//**
284
Commits the mtr and sets the pcur latch mode to BTR_NO_LATCHES,
285
that is, the cursor becomes detached. If there have been modifications
286
to the page where pcur is positioned, this can be used instead of
287
btr_pcur_release_leaf. Function btr_pcur_store_position should be used
288
before calling this, if restoration of cursor is wanted later. */
291
btr_pcur_commit_specify_mtr(
292
/*========================*/
293
btr_pcur_t* pcur, /*!< in: persistent cursor */
294
mtr_t* mtr); /*!< in: mtr to commit */
295
/**************************************************************//**
296
Tests if a cursor is detached: that is the latch mode is BTR_NO_LATCHES.
297
@return TRUE if detached */
300
btr_pcur_is_detached(
301
/*=================*/
302
btr_pcur_t* pcur); /*!< in: persistent cursor */
303
/*********************************************************//**
304
Moves the persistent cursor to the next record in the tree. If no records are
305
left, the cursor stays 'after last in tree'.
306
@return TRUE if the cursor was not after last in tree */
309
btr_pcur_move_to_next(
310
/*==================*/
311
btr_pcur_t* cursor, /*!< in: persistent cursor; NOTE that the
312
function may release the page latch */
313
mtr_t* mtr); /*!< in: mtr */
314
/*********************************************************//**
315
Moves the persistent cursor to the previous record in the tree. If no records
316
are left, the cursor stays 'before first in tree'.
317
@return TRUE if the cursor was not before first in tree */
320
btr_pcur_move_to_prev(
321
/*==================*/
322
btr_pcur_t* cursor, /*!< in: persistent cursor; NOTE that the
323
function may release the page latch */
324
mtr_t* mtr); /*!< in: mtr */
325
/*********************************************************//**
326
Moves the persistent cursor to the last record on the same page. */
329
btr_pcur_move_to_last_on_page(
330
/*==========================*/
331
btr_pcur_t* cursor, /*!< in: persistent cursor */
332
mtr_t* mtr); /*!< in: mtr */
333
/*********************************************************//**
334
Moves the persistent cursor to the next user record in the tree. If no user
335
records are left, the cursor ends up 'after last in tree'.
336
@return TRUE if the cursor moved forward, ending on a user record */
339
btr_pcur_move_to_next_user_rec(
340
/*===========================*/
341
btr_pcur_t* cursor, /*!< in: persistent cursor; NOTE that the
342
function may release the page latch */
343
mtr_t* mtr); /*!< in: mtr */
344
/*********************************************************//**
345
Moves the persistent cursor to the first record on the next page.
346
Releases the latch on the current page, and bufferunfixes it.
347
Note that there must not be modifications on the current page,
348
as then the x-latch can be released only in mtr_commit. */
351
btr_pcur_move_to_next_page(
352
/*=======================*/
353
btr_pcur_t* cursor, /*!< in: persistent cursor; must be on the
354
last record of the current page */
355
mtr_t* mtr); /*!< in: mtr */
356
/*********************************************************//**
357
Moves the persistent cursor backward if it is on the first record
358
of the page. Releases the latch on the current page, and bufferunfixes
359
it. Note that to prevent a possible deadlock, the operation first
360
stores the position of the cursor, releases the leaf latch, acquires
361
necessary latches and restores the cursor position again before returning.
362
The alphabetical position of the cursor is guaranteed to be sensible
363
on return, but it may happen that the cursor is not positioned on the
364
last record of any page, because the structure of the tree may have
365
changed while the cursor had no latches. */
368
btr_pcur_move_backward_from_page(
369
/*=============================*/
370
btr_pcur_t* cursor, /*!< in: persistent cursor, must be on the
371
first record of the current page */
372
mtr_t* mtr); /*!< in: mtr */
374
/*********************************************************//**
375
Returns the btr cursor component of a persistent cursor.
376
@return pointer to btr cursor component */
379
btr_pcur_get_btr_cur(
380
/*=================*/
381
const btr_pcur_t* cursor); /*!< in: persistent cursor */
382
/*********************************************************//**
383
Returns the page cursor component of a persistent cursor.
384
@return pointer to page cursor component */
387
btr_pcur_get_page_cur(
388
/*==================*/
389
const btr_pcur_t* cursor); /*!< in: persistent cursor */
390
#else /* UNIV_DEBUG */
391
# define btr_pcur_get_btr_cur(cursor) (&(cursor)->btr_cur)
392
# define btr_pcur_get_page_cur(cursor) (&(cursor)->btr_cur.page_cur)
393
#endif /* UNIV_DEBUG */
394
/*********************************************************//**
395
Returns the page of a persistent cursor.
396
@return pointer to the page */
401
btr_pcur_t* cursor);/*!< in: persistent cursor */
402
/*********************************************************//**
403
Returns the buffer block of a persistent cursor.
404
@return pointer to the block */
409
btr_pcur_t* cursor);/*!< in: persistent cursor */
410
/*********************************************************//**
411
Returns the record of a persistent cursor.
412
@return pointer to the record */
417
btr_pcur_t* cursor);/*!< in: persistent cursor */
418
/*********************************************************//**
419
Checks if the persistent cursor is on a user record. */
422
btr_pcur_is_on_user_rec(
423
/*====================*/
424
const btr_pcur_t* cursor);/*!< in: persistent cursor */
425
/*********************************************************//**
426
Checks if the persistent cursor is after the last user record on
430
btr_pcur_is_after_last_on_page(
431
/*===========================*/
432
const btr_pcur_t* cursor);/*!< in: persistent cursor */
433
/*********************************************************//**
434
Checks if the persistent cursor is before the first user record on
438
btr_pcur_is_before_first_on_page(
439
/*=============================*/
440
const btr_pcur_t* cursor);/*!< in: persistent cursor */
441
/*********************************************************//**
442
Checks if the persistent cursor is before the first user record in
446
btr_pcur_is_before_first_in_tree(
447
/*=============================*/
448
btr_pcur_t* cursor, /*!< in: persistent cursor */
449
mtr_t* mtr); /*!< in: mtr */
450
/*********************************************************//**
451
Checks if the persistent cursor is after the last user record in
455
btr_pcur_is_after_last_in_tree(
456
/*===========================*/
457
btr_pcur_t* cursor, /*!< in: persistent cursor */
458
mtr_t* mtr); /*!< in: mtr */
459
/*********************************************************//**
460
Moves the persistent cursor to the next record on the same page. */
463
btr_pcur_move_to_next_on_page(
464
/*==========================*/
465
btr_pcur_t* cursor);/*!< in/out: persistent cursor */
466
/*********************************************************//**
467
Moves the persistent cursor to the previous record on the same page. */
470
btr_pcur_move_to_prev_on_page(
471
/*==========================*/
472
btr_pcur_t* cursor);/*!< in/out: persistent cursor */
475
/* The persistent B-tree cursor structure. This is used mainly for SQL
476
selects, updates, and deletes. */
478
struct btr_pcur_struct{
479
btr_cur_t btr_cur; /*!< a B-tree cursor */
480
ulint latch_mode; /*!< see TODO note below!
481
BTR_SEARCH_LEAF, BTR_MODIFY_LEAF,
482
BTR_MODIFY_TREE, or BTR_NO_LATCHES,
483
depending on the latching state of
484
the page and tree where the cursor is
485
positioned; the last value means that
486
the cursor is not currently positioned:
487
we say then that the cursor is
488
detached; it can be restored to
489
attached if the old position was
491
ulint old_stored; /*!< BTR_PCUR_OLD_STORED
492
or BTR_PCUR_OLD_NOT_STORED */
493
rec_t* old_rec; /*!< if cursor position is stored,
494
contains an initial segment of the
495
latest record cursor was positioned
496
either on, before, or after */
497
ulint old_n_fields; /*!< number of fields in old_rec */
498
ulint rel_pos; /*!< BTR_PCUR_ON, BTR_PCUR_BEFORE, or
499
BTR_PCUR_AFTER, depending on whether
500
cursor was on, before, or after the
502
buf_block_t* block_when_stored;/* buffer block when the position was
504
ib_uint64_t modify_clock; /*!< the modify clock value of the
505
buffer block when the cursor position
507
ulint pos_state; /*!< see TODO note below!
508
BTR_PCUR_IS_POSITIONED,
509
BTR_PCUR_WAS_POSITIONED,
510
BTR_PCUR_NOT_POSITIONED */
511
ulint search_mode; /*!< PAGE_CUR_G, ... */
512
trx_t* trx_if_known; /*!< the transaction, if we know it;
513
otherwise this field is not defined;
514
can ONLY BE USED in error prints in
515
fatal assertion failures! */
516
/*-----------------------------*/
517
/* NOTE that the following fields may possess dynamically allocated
518
memory which should be freed if not needed anymore! */
520
mtr_t* mtr; /*!< NULL, or this field may contain
521
a mini-transaction which holds the
522
latch on the cursor page */
523
byte* old_rec_buf; /*!< NULL, or a dynamically allocated
524
buffer for old_rec */
525
ulint buf_size; /*!< old_rec_buf size if old_rec_buf
529
#define BTR_PCUR_IS_POSITIONED 1997660512 /* TODO: currently, the state
530
can be BTR_PCUR_IS_POSITIONED,
531
though it really should be
532
BTR_PCUR_WAS_POSITIONED,
533
because we have no obligation
534
to commit the cursor with
535
mtr; similarly latch_mode may
536
be out of date. This can
537
lead to problems if btr_pcur
538
is not used the right way;
539
all current code should be
541
#define BTR_PCUR_WAS_POSITIONED 1187549791
542
#define BTR_PCUR_NOT_POSITIONED 1328997689
544
#define BTR_PCUR_OLD_STORED 908467085
545
#define BTR_PCUR_OLD_NOT_STORED 122766467
548
#include "btr0pcur.ic"