1
/******************************************************
2
The index tree persistent cursor
6
Created 2/23/1996 Heikki Tuuri
7
*******************************************************/
13
#include "dict0dict.h"
14
#include "data0data.h"
19
#include "btr0types.h"
21
/* Relative positions for a stored cursor position */
23
#define BTR_PCUR_BEFORE 2
24
#define BTR_PCUR_AFTER 3
25
/* Note that if the tree is not empty, btr_pcur_store_position does not
26
use the following, but only uses the above three alternatives, where the
27
position is stored relative to a specific record: this makes implementation
28
of a scroll cursor easier */
29
#define BTR_PCUR_BEFORE_FIRST_IN_TREE 4 /* in an empty tree */
30
#define BTR_PCUR_AFTER_LAST_IN_TREE 5 /* in an empty tree */
32
/******************************************************************
33
Allocates memory for a persistent cursor object and initializes the cursor. */
36
btr_pcur_create_for_mysql(void);
37
/*============================*/
38
/* out, own: persistent cursor */
39
/******************************************************************
40
Frees the memory for a persistent cursor object. */
43
btr_pcur_free_for_mysql(
44
/*====================*/
45
btr_pcur_t* cursor); /* in, own: persistent cursor */
46
/******************************************************************
47
Copies the stored position of a pcur to another pcur. */
50
btr_pcur_copy_stored_position(
51
/*==========================*/
52
btr_pcur_t* pcur_receive, /* in: pcur which will receive the
54
btr_pcur_t* pcur_donate); /* in: pcur from which the info is
56
/******************************************************************
57
Sets the old_rec_buf field to NULL. */
62
btr_pcur_t* pcur); /* in: persistent cursor */
63
/******************************************************************
64
Initializes and opens a persistent cursor to an index tree. It should be
65
closed with btr_pcur_close. */
70
dict_index_t* index, /* in: index */
71
dtuple_t* tuple, /* in: tuple on which search done */
72
ulint mode, /* in: PAGE_CUR_L, ...;
73
NOTE that if the search is made using a unique
74
prefix of a record, mode should be
75
PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
76
may end up on the previous page from the
78
ulint latch_mode,/* in: BTR_SEARCH_LEAF, ... */
79
btr_pcur_t* cursor, /* in: memory buffer for persistent cursor */
80
mtr_t* mtr); /* in: mtr */
81
/******************************************************************
82
Opens an persistent cursor to an index tree without initializing the
86
btr_pcur_open_with_no_init(
87
/*=======================*/
88
dict_index_t* index, /* in: index */
89
dtuple_t* tuple, /* in: tuple on which search done */
90
ulint mode, /* in: PAGE_CUR_L, ...;
91
NOTE that if the search is made using a unique
92
prefix of a record, mode should be
93
PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
94
may end up on the previous page of the
96
ulint latch_mode,/* in: BTR_SEARCH_LEAF, ...;
97
NOTE that if has_search_latch != 0 then
98
we maybe do not acquire a latch on the cursor
99
page, but assume that the caller uses his
100
btr search latch to protect the record! */
101
btr_pcur_t* cursor, /* in: memory buffer for persistent cursor */
102
ulint has_search_latch,/* in: latch mode the caller
103
currently has on btr_search_latch:
105
mtr_t* mtr); /* in: mtr */
106
/*********************************************************************
107
Opens a persistent cursor at either end of an index. */
110
btr_pcur_open_at_index_side(
111
/*========================*/
112
ibool from_left, /* in: TRUE if open to the low end,
113
FALSE if to the high end */
114
dict_index_t* index, /* in: index */
115
ulint latch_mode, /* in: latch mode */
116
btr_pcur_t* pcur, /* in: cursor */
117
ibool do_init, /* in: TRUE if should be initialized */
118
mtr_t* mtr); /* in: mtr */
119
/******************************************************************
120
Gets the up_match value for a pcur after a search. */
123
btr_pcur_get_up_match(
124
/*==================*/
125
/* out: number of matched fields at the cursor
126
or to the right if search mode was PAGE_CUR_GE,
127
otherwise undefined */
128
btr_pcur_t* cursor); /* in: memory buffer for persistent cursor */
129
/******************************************************************
130
Gets the low_match value for a pcur after a search. */
133
btr_pcur_get_low_match(
134
/*===================*/
135
/* out: number of matched fields at the cursor
136
or to the right if search mode was PAGE_CUR_LE,
137
otherwise undefined */
138
btr_pcur_t* cursor); /* in: memory buffer for persistent cursor */
139
/******************************************************************
140
If mode is PAGE_CUR_G or PAGE_CUR_GE, opens a persistent cursor on the first
141
user record satisfying the search condition, in the case PAGE_CUR_L or
142
PAGE_CUR_LE, on the last user record. If no such user record exists, then
143
in the first case sets the cursor after last in tree, and in the latter case
144
before first in tree. The latching mode must be BTR_SEARCH_LEAF or
148
btr_pcur_open_on_user_rec(
149
/*======================*/
150
dict_index_t* index, /* in: index */
151
dtuple_t* tuple, /* in: tuple on which search done */
152
ulint mode, /* in: PAGE_CUR_L, ... */
153
ulint latch_mode, /* in: BTR_SEARCH_LEAF or
155
btr_pcur_t* cursor, /* in: memory buffer for persistent
157
mtr_t* mtr); /* in: mtr */
158
/**************************************************************************
159
Positions a cursor at a randomly chosen position within a B-tree. */
162
btr_pcur_open_at_rnd_pos(
163
/*=====================*/
164
dict_index_t* index, /* in: index */
165
ulint latch_mode, /* in: BTR_SEARCH_LEAF, ... */
166
btr_pcur_t* cursor, /* in/out: B-tree pcur */
167
mtr_t* mtr); /* in: mtr */
168
/******************************************************************
169
Frees the possible old_rec_buf buffer of a persistent cursor and sets the
170
latch mode of the persistent cursor to BTR_NO_LATCHES. */
175
btr_pcur_t* cursor); /* in: persistent cursor */
176
/******************************************************************
177
The position of the cursor is stored by taking an initial segment of the
178
record the cursor is positioned on, before, or after, and copying it to the
179
cursor data structure, or just setting a flag if the cursor id before the
180
first in an EMPTY tree, or after the last in an EMPTY tree. NOTE that the
181
page where the cursor is positioned must not be empty if the index tree is
182
not totally empty! */
185
btr_pcur_store_position(
186
/*====================*/
187
btr_pcur_t* cursor, /* in: persistent cursor */
188
mtr_t* mtr); /* in: mtr */
189
/******************************************************************
190
Restores the stored position of a persistent cursor bufferfixing the page and
191
obtaining the specified latches. If the cursor position was saved when the
192
(1) cursor was positioned on a user record: this function restores the position
193
to the last record LESS OR EQUAL to the stored record;
194
(2) cursor was positioned on a page infimum record: restores the position to
195
the last record LESS than the user record which was the successor of the page
197
(3) cursor was positioned on the page supremum: restores to the first record
198
GREATER than the user record which was the predecessor of the supremum.
199
(4) cursor was positioned before the first or after the last in an empty tree:
200
restores to before first or after the last in the tree. */
203
btr_pcur_restore_position(
204
/*======================*/
205
/* out: TRUE if the cursor position
206
was stored when it was on a user record
207
and it can be restored on a user record
208
whose ordering fields are identical to
209
the ones of the original user record */
210
ulint latch_mode, /* in: BTR_SEARCH_LEAF, ... */
211
btr_pcur_t* cursor, /* in: detached persistent cursor */
212
mtr_t* mtr); /* in: mtr */
213
/******************************************************************
214
If the latch mode of the cursor is BTR_LEAF_SEARCH or BTR_LEAF_MODIFY,
215
releases the page latch and bufferfix reserved by the cursor.
216
NOTE! In the case of BTR_LEAF_MODIFY, there should not exist changes
217
made by the current mini-transaction to the data protected by the
218
cursor latch, as then the latch must not be released until mtr_commit. */
221
btr_pcur_release_leaf(
222
/*==================*/
223
btr_pcur_t* cursor, /* in: persistent cursor */
224
mtr_t* mtr); /* in: mtr */
225
/*************************************************************
226
Gets the rel_pos field for a cursor whose position has been stored. */
229
btr_pcur_get_rel_pos(
230
/*=================*/
231
/* out: BTR_PCUR_ON, ... */
232
btr_pcur_t* cursor);/* in: persistent cursor */
233
/*************************************************************
234
Sets the mtr field for a pcur. */
239
btr_pcur_t* cursor, /* in: persistent cursor */
240
mtr_t* mtr); /* in, own: mtr */
241
/*************************************************************
242
Gets the mtr field for a pcur. */
248
btr_pcur_t* cursor); /* in: persistent cursor */
249
/******************************************************************
250
Commits the pcur mtr and sets the pcur latch mode to BTR_NO_LATCHES,
251
that is, the cursor becomes detached. If there have been modifications
252
to the page where pcur is positioned, this can be used instead of
253
btr_pcur_release_leaf. Function btr_pcur_store_position should be used
254
before calling this, if restoration of cursor is wanted later. */
259
btr_pcur_t* pcur); /* in: persistent cursor */
260
/******************************************************************
261
Differs from btr_pcur_commit in that we can specify the mtr to commit. */
264
btr_pcur_commit_specify_mtr(
265
/*========================*/
266
btr_pcur_t* pcur, /* in: persistent cursor */
267
mtr_t* mtr); /* in: mtr to commit */
268
/******************************************************************
269
Tests if a cursor is detached: that is the latch mode is BTR_NO_LATCHES. */
272
btr_pcur_is_detached(
273
/*=================*/
274
/* out: TRUE if detached */
275
btr_pcur_t* pcur); /* in: persistent cursor */
276
/*************************************************************
277
Moves the persistent cursor to the next record in the tree. If no records are
278
left, the cursor stays 'after last in tree'. */
281
btr_pcur_move_to_next(
282
/*==================*/
283
/* out: TRUE if the cursor was not after last
285
btr_pcur_t* cursor, /* in: persistent cursor; NOTE that the
286
function may release the page latch */
287
mtr_t* mtr); /* in: mtr */
288
/*************************************************************
289
Moves the persistent cursor to the previous record in the tree. If no records
290
are left, the cursor stays 'before first in tree'. */
293
btr_pcur_move_to_prev(
294
/*==================*/
295
/* out: TRUE if the cursor was not before first
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 last record on the same page. */
304
btr_pcur_move_to_last_on_page(
305
/*==========================*/
306
btr_pcur_t* cursor, /* in: persistent cursor */
307
mtr_t* mtr); /* in: mtr */
308
/*************************************************************
309
Moves the persistent cursor to the next user record in the tree. If no user
310
records are left, the cursor ends up 'after last in tree'. */
313
btr_pcur_move_to_next_user_rec(
314
/*===========================*/
315
/* out: TRUE if the cursor moved forward,
316
ending on a user record */
317
btr_pcur_t* cursor, /* in: persistent cursor; NOTE that the
318
function may release the page latch */
319
mtr_t* mtr); /* in: mtr */
320
/*************************************************************
321
Moves the persistent cursor to the first record on the next page.
322
Releases the latch on the current page, and bufferunfixes it.
323
Note that there must not be modifications on the current page,
324
as then the x-latch can be released only in mtr_commit. */
327
btr_pcur_move_to_next_page(
328
/*=======================*/
329
btr_pcur_t* cursor, /* in: persistent cursor; must be on the
330
last record of the current page */
331
mtr_t* mtr); /* in: mtr */
332
/*************************************************************
333
Moves the persistent cursor backward if it is on the first record
334
of the page. Releases the latch on the current page, and bufferunfixes
335
it. Note that to prevent a possible deadlock, the operation first
336
stores the position of the cursor, releases the leaf latch, acquires
337
necessary latches and restores the cursor position again before returning.
338
The alphabetical position of the cursor is guaranteed to be sensible
339
on return, but it may happen that the cursor is not positioned on the
340
last record of any page, because the structure of the tree may have
341
changed while the cursor had no latches. */
344
btr_pcur_move_backward_from_page(
345
/*=============================*/
346
btr_pcur_t* cursor, /* in: persistent cursor, must be on the
347
first record of the current page */
348
mtr_t* mtr); /* in: mtr */
349
/*************************************************************
350
Returns the btr cursor component of a persistent cursor. */
353
btr_pcur_get_btr_cur(
354
/*=================*/
355
/* out: pointer to btr cursor component */
356
btr_pcur_t* cursor); /* in: persistent cursor */
357
/*************************************************************
358
Returns the page cursor component of a persistent cursor. */
361
btr_pcur_get_page_cur(
362
/*==================*/
363
/* out: pointer to page cursor component */
364
btr_pcur_t* cursor); /* in: persistent cursor */
365
/*************************************************************
366
Returns the page of a persistent cursor. */
371
/* out: pointer to the page */
372
btr_pcur_t* cursor);/* in: persistent cursor */
373
/*************************************************************
374
Returns the record of a persistent cursor. */
379
/* out: pointer to the record */
380
btr_pcur_t* cursor);/* in: persistent cursor */
381
/*************************************************************
382
Checks if the persistent cursor is on a user record. */
385
btr_pcur_is_on_user_rec(
386
/*====================*/
387
btr_pcur_t* cursor, /* in: persistent cursor */
388
mtr_t* mtr); /* in: mtr */
389
/*************************************************************
390
Checks if the persistent cursor is after the last user record on
394
btr_pcur_is_after_last_on_page(
395
/*===========================*/
396
btr_pcur_t* cursor, /* in: persistent cursor */
397
mtr_t* mtr); /* in: mtr */
398
/*************************************************************
399
Checks if the persistent cursor is before the first user record on
403
btr_pcur_is_before_first_on_page(
404
/*=============================*/
405
btr_pcur_t* cursor, /* in: persistent cursor */
406
mtr_t* mtr); /* in: mtr */
407
/*************************************************************
408
Checks if the persistent cursor is before the first user record in
412
btr_pcur_is_before_first_in_tree(
413
/*=============================*/
414
btr_pcur_t* cursor, /* in: persistent cursor */
415
mtr_t* mtr); /* in: mtr */
416
/*************************************************************
417
Checks if the persistent cursor is after the last user record in
421
btr_pcur_is_after_last_in_tree(
422
/*===========================*/
423
btr_pcur_t* cursor, /* in: persistent cursor */
424
mtr_t* mtr); /* in: mtr */
425
/*************************************************************
426
Moves the persistent cursor to the next record on the same page. */
429
btr_pcur_move_to_next_on_page(
430
/*==========================*/
431
btr_pcur_t* cursor, /* in: persistent cursor */
432
mtr_t* mtr); /* in: mtr */
433
/*************************************************************
434
Moves the persistent cursor to the previous record on the same page. */
437
btr_pcur_move_to_prev_on_page(
438
/*==========================*/
439
btr_pcur_t* cursor, /* in: persistent cursor */
440
mtr_t* mtr); /* in: mtr */
443
/* The persistent B-tree cursor structure. This is used mainly for SQL
444
selects, updates, and deletes. */
446
struct btr_pcur_struct{
447
btr_cur_t btr_cur; /* a B-tree cursor */
448
ulint latch_mode; /* see TODO note below!
449
BTR_SEARCH_LEAF, BTR_MODIFY_LEAF,
450
BTR_MODIFY_TREE, or BTR_NO_LATCHES,
451
depending on the latching state of
452
the page and tree where the cursor is
453
positioned; the last value means that
454
the cursor is not currently positioned:
455
we say then that the cursor is
456
detached; it can be restored to
457
attached if the old position was
459
ulint old_stored; /* BTR_PCUR_OLD_STORED
460
or BTR_PCUR_OLD_NOT_STORED */
461
rec_t* old_rec; /* if cursor position is stored,
462
contains an initial segment of the
463
latest record cursor was positioned
464
either on, before, or after */
465
ulint old_n_fields; /* number of fields in old_rec */
466
ulint rel_pos; /* BTR_PCUR_ON, BTR_PCUR_BEFORE, or
467
BTR_PCUR_AFTER, depending on whether
468
cursor was on, before, or after the
470
buf_block_t* block_when_stored;/* buffer block when the position was
471
stored; note that if AWE is on, frames
473
dulint modify_clock; /* the modify clock value of the
474
buffer block when the cursor position
476
ulint pos_state; /* see TODO note below!
477
BTR_PCUR_IS_POSITIONED,
478
BTR_PCUR_WAS_POSITIONED,
479
BTR_PCUR_NOT_POSITIONED */
480
ulint search_mode; /* PAGE_CUR_G, ... */
481
trx_t* trx_if_known; /* the transaction, if we know it;
482
otherwise this field is not defined;
483
can ONLY BE USED in error prints in
484
fatal assertion failures! */
485
/*-----------------------------*/
486
/* NOTE that the following fields may possess dynamically allocated
487
memory which should be freed if not needed anymore! */
489
mtr_t* mtr; /* NULL, or this field may contain
490
a mini-transaction which holds the
491
latch on the cursor page */
492
byte* old_rec_buf; /* NULL, or a dynamically allocated
493
buffer for old_rec */
494
ulint buf_size; /* old_rec_buf size if old_rec_buf
498
#define BTR_PCUR_IS_POSITIONED 1997660512 /* TODO: currently, the state
499
can be BTR_PCUR_IS_POSITIONED,
500
though it really should be
501
BTR_PCUR_WAS_POSITIONED,
502
because we have no obligation
503
to commit the cursor with
504
mtr; similarly latch_mode may
505
be out of date. This can
506
lead to problems if btr_pcur
507
is not used the right way;
508
all current code should be
510
#define BTR_PCUR_WAS_POSITIONED 1187549791
511
#define BTR_PCUR_NOT_POSITIONED 1328997689
513
#define BTR_PCUR_OLD_STORED 908467085
514
#define BTR_PCUR_OLD_NOT_STORED 122766467
517
#include "btr0pcur.ic"