1
/*****************************************************************************
3
Copyright (c) 1996, 2009, 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
mtr_t* mtr); /*!< in: mtr */
98
/**************************************************************//**
99
Opens an persistent cursor to an index tree without initializing the
103
btr_pcur_open_with_no_init(
104
/*=======================*/
105
dict_index_t* index, /*!< in: index */
106
const dtuple_t* tuple, /*!< in: tuple on which search done */
107
ulint mode, /*!< in: PAGE_CUR_L, ...;
108
NOTE that if the search is made using a unique
109
prefix of a record, mode should be
110
PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
111
may end up on the previous page of the
113
ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ...;
114
NOTE that if has_search_latch != 0 then
115
we maybe do not acquire a latch on the cursor
116
page, but assume that the caller uses his
117
btr search latch to protect the record! */
118
btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
119
ulint has_search_latch,/*!< in: latch mode the caller
120
currently has on btr_search_latch:
122
mtr_t* mtr); /*!< in: mtr */
123
/*****************************************************************//**
124
Opens a persistent cursor at either end of an index. */
127
btr_pcur_open_at_index_side(
128
/*========================*/
129
ibool from_left, /*!< in: TRUE if open to the low end,
130
FALSE if to the high end */
131
dict_index_t* index, /*!< in: index */
132
ulint latch_mode, /*!< in: latch mode */
133
btr_pcur_t* pcur, /*!< in: cursor */
134
ibool do_init, /*!< in: TRUE if should be initialized */
135
mtr_t* mtr); /*!< in: mtr */
136
/**************************************************************//**
137
Gets the up_match value for a pcur after a search.
138
@return number of matched fields at the cursor or to the right if
139
search mode was PAGE_CUR_GE, otherwise undefined */
142
btr_pcur_get_up_match(
143
/*==================*/
144
btr_pcur_t* cursor); /*!< in: memory buffer for persistent cursor */
145
/**************************************************************//**
146
Gets the low_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_LE, otherwise undefined */
151
btr_pcur_get_low_match(
152
/*===================*/
153
btr_pcur_t* cursor); /*!< in: memory buffer for persistent cursor */
154
/**************************************************************//**
155
If mode is PAGE_CUR_G or PAGE_CUR_GE, opens a persistent cursor on the first
156
user record satisfying the search condition, in the case PAGE_CUR_L or
157
PAGE_CUR_LE, on the last user record. If no such user record exists, then
158
in the first case sets the cursor after last in tree, and in the latter case
159
before first in tree. The latching mode must be BTR_SEARCH_LEAF or
163
btr_pcur_open_on_user_rec(
164
/*======================*/
165
dict_index_t* index, /*!< in: index */
166
const dtuple_t* tuple, /*!< in: tuple on which search done */
167
ulint mode, /*!< in: PAGE_CUR_L, ... */
168
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF or
170
btr_pcur_t* cursor, /*!< in: memory buffer for persistent
172
mtr_t* mtr); /*!< in: mtr */
173
/**********************************************************************//**
174
Positions a cursor at a randomly chosen position within a B-tree. */
177
btr_pcur_open_at_rnd_pos(
178
/*=====================*/
179
dict_index_t* index, /*!< in: index */
180
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */
181
btr_pcur_t* cursor, /*!< in/out: B-tree pcur */
182
mtr_t* mtr); /*!< in: mtr */
183
/**************************************************************//**
184
Frees the possible old_rec_buf buffer of a persistent cursor and sets the
185
latch mode of the persistent cursor to BTR_NO_LATCHES. */
190
btr_pcur_t* cursor); /*!< in: persistent cursor */
191
/**************************************************************//**
192
The position of the cursor is stored by taking an initial segment of the
193
record the cursor is positioned on, before, or after, and copying it to the
194
cursor data structure, or just setting a flag if the cursor id before the
195
first in an EMPTY tree, or after the last in an EMPTY tree. NOTE that the
196
page where the cursor is positioned must not be empty if the index tree is
197
not totally empty! */
200
btr_pcur_store_position(
201
/*====================*/
202
btr_pcur_t* cursor, /*!< in: persistent cursor */
203
mtr_t* mtr); /*!< in: mtr */
204
/**************************************************************//**
205
Restores the stored position of a persistent cursor bufferfixing the page and
206
obtaining the specified latches. If the cursor position was saved when the
207
(1) cursor was positioned on a user record: this function restores the position
208
to the last record LESS OR EQUAL to the stored record;
209
(2) cursor was positioned on a page infimum record: restores the position to
210
the last record LESS than the user record which was the successor of the page
212
(3) cursor was positioned on the page supremum: restores to the first record
213
GREATER than the user record which was the predecessor of the supremum.
214
(4) cursor was positioned before the first or after the last in an empty tree:
215
restores to before first or after the last in the tree.
216
@return TRUE if the cursor position was stored when it was on a user
217
record and it can be restored on a user record whose ordering fields
218
are identical to the ones of the original user record */
221
btr_pcur_restore_position(
222
/*======================*/
223
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */
224
btr_pcur_t* cursor, /*!< in: detached persistent cursor */
225
mtr_t* mtr); /*!< in: mtr */
226
/**************************************************************//**
227
If the latch mode of the cursor is BTR_LEAF_SEARCH or BTR_LEAF_MODIFY,
228
releases the page latch and bufferfix reserved by the cursor.
229
NOTE! In the case of BTR_LEAF_MODIFY, there should not exist changes
230
made by the current mini-transaction to the data protected by the
231
cursor latch, as then the latch must not be released until mtr_commit. */
234
btr_pcur_release_leaf(
235
/*==================*/
236
btr_pcur_t* cursor, /*!< in: persistent cursor */
237
mtr_t* mtr); /*!< in: mtr */
238
/*********************************************************//**
239
Gets the rel_pos field for a cursor whose position has been stored.
240
@return BTR_PCUR_ON, ... */
243
btr_pcur_get_rel_pos(
244
/*=================*/
245
const btr_pcur_t* cursor);/*!< in: persistent cursor */
246
/*********************************************************//**
247
Sets the mtr field for a pcur. */
252
btr_pcur_t* cursor, /*!< in: persistent cursor */
253
mtr_t* mtr); /*!< in, own: mtr */
254
/*********************************************************//**
255
Gets the mtr field for a pcur.
261
btr_pcur_t* cursor); /*!< in: persistent cursor */
262
/**************************************************************//**
263
Commits the pcur mtr and sets the pcur latch mode to BTR_NO_LATCHES,
264
that is, the cursor becomes detached. If there have been modifications
265
to the page where pcur is positioned, this can be used instead of
266
btr_pcur_release_leaf. Function btr_pcur_store_position should be used
267
before calling this, if restoration of cursor is wanted later. */
272
btr_pcur_t* pcur); /*!< in: persistent cursor */
273
/**************************************************************//**
274
Differs from btr_pcur_commit in that we can specify the mtr to commit. */
277
btr_pcur_commit_specify_mtr(
278
/*========================*/
279
btr_pcur_t* pcur, /*!< in: persistent cursor */
280
mtr_t* mtr); /*!< in: mtr to commit */
281
/**************************************************************//**
282
Tests if a cursor is detached: that is the latch mode is BTR_NO_LATCHES.
283
@return TRUE if detached */
286
btr_pcur_is_detached(
287
/*=================*/
288
btr_pcur_t* pcur); /*!< in: persistent cursor */
289
/*********************************************************//**
290
Moves the persistent cursor to the next record in the tree. If no records are
291
left, the cursor stays 'after last in tree'.
292
@return TRUE if the cursor was not after last in tree */
295
btr_pcur_move_to_next(
296
/*==================*/
297
btr_pcur_t* cursor, /*!< in: persistent cursor; NOTE that the
298
function may release the page latch */
299
mtr_t* mtr); /*!< in: mtr */
300
/*********************************************************//**
301
Moves the persistent cursor to the previous record in the tree. If no records
302
are left, the cursor stays 'before first in tree'.
303
@return TRUE if the cursor was not before first in tree */
306
btr_pcur_move_to_prev(
307
/*==================*/
308
btr_pcur_t* cursor, /*!< in: persistent cursor; NOTE that the
309
function may release the page latch */
310
mtr_t* mtr); /*!< in: mtr */
311
/*********************************************************//**
312
Moves the persistent cursor to the last record on the same page. */
315
btr_pcur_move_to_last_on_page(
316
/*==========================*/
317
btr_pcur_t* cursor, /*!< in: persistent cursor */
318
mtr_t* mtr); /*!< in: mtr */
319
/*********************************************************//**
320
Moves the persistent cursor to the next user record in the tree. If no user
321
records are left, the cursor ends up 'after last in tree'.
322
@return TRUE if the cursor moved forward, ending on a user record */
325
btr_pcur_move_to_next_user_rec(
326
/*===========================*/
327
btr_pcur_t* cursor, /*!< in: persistent cursor; NOTE that the
328
function may release the page latch */
329
mtr_t* mtr); /*!< in: mtr */
330
/*********************************************************//**
331
Moves the persistent cursor to the first record on the next page.
332
Releases the latch on the current page, and bufferunfixes it.
333
Note that there must not be modifications on the current page,
334
as then the x-latch can be released only in mtr_commit. */
337
btr_pcur_move_to_next_page(
338
/*=======================*/
339
btr_pcur_t* cursor, /*!< in: persistent cursor; must be on the
340
last record of the current page */
341
mtr_t* mtr); /*!< in: mtr */
342
/*********************************************************//**
343
Moves the persistent cursor backward if it is on the first record
344
of the page. Releases the latch on the current page, and bufferunfixes
345
it. Note that to prevent a possible deadlock, the operation first
346
stores the position of the cursor, releases the leaf latch, acquires
347
necessary latches and restores the cursor position again before returning.
348
The alphabetical position of the cursor is guaranteed to be sensible
349
on return, but it may happen that the cursor is not positioned on the
350
last record of any page, because the structure of the tree may have
351
changed while the cursor had no latches. */
354
btr_pcur_move_backward_from_page(
355
/*=============================*/
356
btr_pcur_t* cursor, /*!< in: persistent cursor, must be on the
357
first record of the current page */
358
mtr_t* mtr); /*!< in: mtr */
360
/*********************************************************//**
361
Returns the btr cursor component of a persistent cursor.
362
@return pointer to btr cursor component */
365
btr_pcur_get_btr_cur(
366
/*=================*/
367
const btr_pcur_t* cursor); /*!< in: persistent cursor */
368
/*********************************************************//**
369
Returns the page cursor component of a persistent cursor.
370
@return pointer to page cursor component */
373
btr_pcur_get_page_cur(
374
/*==================*/
375
const btr_pcur_t* cursor); /*!< in: persistent cursor */
376
#else /* UNIV_DEBUG */
377
# define btr_pcur_get_btr_cur(cursor) (&(cursor)->btr_cur)
378
# define btr_pcur_get_page_cur(cursor) (&(cursor)->btr_cur.page_cur)
379
#endif /* UNIV_DEBUG */
380
/*********************************************************//**
381
Returns the page of a persistent cursor.
382
@return pointer to the page */
387
btr_pcur_t* cursor);/*!< in: persistent cursor */
388
/*********************************************************//**
389
Returns the buffer block of a persistent cursor.
390
@return pointer to the block */
395
btr_pcur_t* cursor);/*!< in: persistent cursor */
396
/*********************************************************//**
397
Returns the record of a persistent cursor.
398
@return pointer to the record */
403
btr_pcur_t* cursor);/*!< in: persistent cursor */
404
/*********************************************************//**
405
Checks if the persistent cursor is on a user record. */
408
btr_pcur_is_on_user_rec(
409
/*====================*/
410
const btr_pcur_t* cursor);/*!< in: persistent cursor */
411
/*********************************************************//**
412
Checks if the persistent cursor is after the last user record on
416
btr_pcur_is_after_last_on_page(
417
/*===========================*/
418
const btr_pcur_t* cursor);/*!< in: persistent cursor */
419
/*********************************************************//**
420
Checks if the persistent cursor is before the first user record on
424
btr_pcur_is_before_first_on_page(
425
/*=============================*/
426
const btr_pcur_t* cursor);/*!< in: persistent cursor */
427
/*********************************************************//**
428
Checks if the persistent cursor is before the first user record in
432
btr_pcur_is_before_first_in_tree(
433
/*=============================*/
434
btr_pcur_t* cursor, /*!< in: persistent cursor */
435
mtr_t* mtr); /*!< in: mtr */
436
/*********************************************************//**
437
Checks if the persistent cursor is after the last user record in
441
btr_pcur_is_after_last_in_tree(
442
/*===========================*/
443
btr_pcur_t* cursor, /*!< in: persistent cursor */
444
mtr_t* mtr); /*!< in: mtr */
445
/*********************************************************//**
446
Moves the persistent cursor to the next record on the same page. */
449
btr_pcur_move_to_next_on_page(
450
/*==========================*/
451
btr_pcur_t* cursor);/*!< in/out: persistent cursor */
452
/*********************************************************//**
453
Moves the persistent cursor to the previous record on the same page. */
456
btr_pcur_move_to_prev_on_page(
457
/*==========================*/
458
btr_pcur_t* cursor);/*!< in/out: persistent cursor */
461
/* The persistent B-tree cursor structure. This is used mainly for SQL
462
selects, updates, and deletes. */
464
struct btr_pcur_struct{
465
btr_cur_t btr_cur; /*!< a B-tree cursor */
466
ulint latch_mode; /*!< see TODO note below!
467
BTR_SEARCH_LEAF, BTR_MODIFY_LEAF,
468
BTR_MODIFY_TREE, or BTR_NO_LATCHES,
469
depending on the latching state of
470
the page and tree where the cursor is
471
positioned; the last value means that
472
the cursor is not currently positioned:
473
we say then that the cursor is
474
detached; it can be restored to
475
attached if the old position was
477
ulint old_stored; /*!< BTR_PCUR_OLD_STORED
478
or BTR_PCUR_OLD_NOT_STORED */
479
rec_t* old_rec; /*!< if cursor position is stored,
480
contains an initial segment of the
481
latest record cursor was positioned
482
either on, before, or after */
483
ulint old_n_fields; /*!< number of fields in old_rec */
484
ulint rel_pos; /*!< BTR_PCUR_ON, BTR_PCUR_BEFORE, or
485
BTR_PCUR_AFTER, depending on whether
486
cursor was on, before, or after the
488
buf_block_t* block_when_stored;/* buffer block when the position was
490
ib_uint64_t modify_clock; /*!< the modify clock value of the
491
buffer block when the cursor position
493
ulint pos_state; /*!< see TODO note below!
494
BTR_PCUR_IS_POSITIONED,
495
BTR_PCUR_WAS_POSITIONED,
496
BTR_PCUR_NOT_POSITIONED */
497
ulint search_mode; /*!< PAGE_CUR_G, ... */
498
trx_t* trx_if_known; /*!< the transaction, if we know it;
499
otherwise this field is not defined;
500
can ONLY BE USED in error prints in
501
fatal assertion failures! */
502
/*-----------------------------*/
503
/* NOTE that the following fields may possess dynamically allocated
504
memory which should be freed if not needed anymore! */
506
mtr_t* mtr; /*!< NULL, or this field may contain
507
a mini-transaction which holds the
508
latch on the cursor page */
509
byte* old_rec_buf; /*!< NULL, or a dynamically allocated
510
buffer for old_rec */
511
ulint buf_size; /*!< old_rec_buf size if old_rec_buf
515
#define BTR_PCUR_IS_POSITIONED 1997660512 /* TODO: currently, the state
516
can be BTR_PCUR_IS_POSITIONED,
517
though it really should be
518
BTR_PCUR_WAS_POSITIONED,
519
because we have no obligation
520
to commit the cursor with
521
mtr; similarly latch_mode may
522
be out of date. This can
523
lead to problems if btr_pcur
524
is not used the right way;
525
all current code should be
527
#define BTR_PCUR_WAS_POSITIONED 1187549791
528
#define BTR_PCUR_NOT_POSITIONED 1328997689
530
#define BTR_PCUR_OLD_STORED 908467085
531
#define BTR_PCUR_OLD_NOT_STORED 122766467
534
#include "btr0pcur.ic"