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
26
/******************************************************************
27
Allocates memory for a persistent cursor object and initializes the cursor. */
30
btr_pcur_create_for_mysql(void);
31
/*============================*/
32
/* out, own: persistent cursor */
33
/******************************************************************
34
Frees the memory for a persistent cursor object. */
37
btr_pcur_free_for_mysql(
38
/*====================*/
39
btr_pcur_t* cursor); /* in, own: persistent cursor */
40
/******************************************************************
41
Copies the stored position of a pcur to another pcur. */
44
btr_pcur_copy_stored_position(
45
/*==========================*/
46
btr_pcur_t* pcur_receive, /* in: pcur which will receive the
48
btr_pcur_t* pcur_donate); /* in: pcur from which the info is
50
/******************************************************************
51
Sets the old_rec_buf field to NULL. */
56
btr_pcur_t* pcur); /* in: persistent cursor */
57
/******************************************************************
58
Initializes and opens a persistent cursor to an index tree. It should be
59
closed with btr_pcur_close. */
64
dict_index_t* index, /* in: index */
65
dtuple_t* tuple, /* in: tuple on which search done */
66
ulint mode, /* in: PAGE_CUR_L, ...;
67
NOTE that if the search is made using a unique
68
prefix of a record, mode should be
69
PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
70
may end up on the previous page from the
72
ulint latch_mode,/* in: BTR_SEARCH_LEAF, ... */
73
btr_pcur_t* cursor, /* in: memory buffer for persistent cursor */
74
mtr_t* mtr); /* in: mtr */
75
/******************************************************************
76
Opens an persistent cursor to an index tree without initializing the
80
btr_pcur_open_with_no_init(
81
/*=======================*/
82
dict_index_t* index, /* in: index */
83
dtuple_t* tuple, /* in: tuple on which search done */
84
ulint mode, /* in: PAGE_CUR_L, ...;
85
NOTE that if the search is made using a unique
86
prefix of a record, mode should be
87
PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
88
may end up on the previous page of the
90
ulint latch_mode,/* in: BTR_SEARCH_LEAF, ... */
91
btr_pcur_t* cursor, /* in: memory buffer for persistent cursor */
92
ulint has_search_latch,/* in: latch mode the caller
93
currently has on btr_search_latch:
95
mtr_t* mtr); /* in: mtr */
96
/*********************************************************************
97
Opens a persistent cursor at either end of an index. */
100
btr_pcur_open_at_index_side(
101
/*========================*/
102
ibool from_left, /* in: TRUE if open to the low end,
103
FALSE if to the high end */
104
dict_index_t* index, /* in: index */
105
ulint latch_mode, /* in: latch mode */
106
btr_pcur_t* pcur, /* in: cursor */
107
ibool do_init, /* in: TRUE if should be initialized */
108
mtr_t* mtr); /* in: mtr */
109
/******************************************************************
110
Gets the up_match value for a pcur after a search. */
113
btr_pcur_get_up_match(
114
/*==================*/
115
/* out: number of matched fields at the cursor
116
or to the right if search mode was PAGE_CUR_GE,
117
otherwise undefined */
118
btr_pcur_t* cursor); /* in: memory buffer for persistent cursor */
119
/******************************************************************
120
Gets the low_match value for a pcur after a search. */
123
btr_pcur_get_low_match(
124
/*===================*/
125
/* out: number of matched fields at the cursor
126
or to the right if search mode was PAGE_CUR_LE,
127
otherwise undefined */
128
btr_pcur_t* cursor); /* in: memory buffer for persistent cursor */
129
/******************************************************************
130
If mode is PAGE_CUR_G or PAGE_CUR_GE, opens a persistent cursor on the first
131
user record satisfying the search condition, in the case PAGE_CUR_L or
132
PAGE_CUR_LE, on the last user record. If no such user record exists, then
133
in the first case sets the cursor after last in tree, and in the latter case
134
before first in tree. The latching mode must be BTR_SEARCH_LEAF or
138
btr_pcur_open_on_user_rec(
139
/*======================*/
140
dict_index_t* index, /* in: index */
141
dtuple_t* tuple, /* in: tuple on which search done */
142
ulint mode, /* in: PAGE_CUR_L, ... */
143
ulint latch_mode, /* in: BTR_SEARCH_LEAF or
145
btr_pcur_t* cursor, /* in: memory buffer for persistent
147
mtr_t* mtr); /* in: mtr */
148
/**************************************************************************
149
Positions a cursor at a randomly chosen position within a B-tree. */
152
btr_pcur_open_at_rnd_pos(
153
/*=====================*/
154
dict_index_t* index, /* in: index */
155
ulint latch_mode, /* in: BTR_SEARCH_LEAF, ... */
156
btr_pcur_t* cursor, /* in/out: B-tree pcur */
157
mtr_t* mtr); /* in: mtr */
158
/******************************************************************
159
Frees the possible old_rec_buf buffer of a persistent cursor and sets the
160
latch mode of the persistent cursor to BTR_NO_LATCHES. */
165
btr_pcur_t* cursor); /* in: persistent cursor */
166
/******************************************************************
167
The position of the cursor is stored by taking an initial segment of the
168
record the cursor is positioned on, before, or after, and copying it to the
169
cursor data structure. NOTE that the page where the cursor is positioned
170
must not be empty! */
173
btr_pcur_store_position(
174
/*====================*/
175
btr_pcur_t* cursor, /* in: persistent cursor */
176
mtr_t* mtr); /* in: mtr */
177
/******************************************************************
178
If the latch mode of the cursor is BTR_LEAF_SEARCH or BTR_LEAF_MODIFY,
179
releases the page latch and bufferfix reserved by the cursor.
180
NOTE! In the case of BTR_LEAF_MODIFY, there should not exist changes
181
made by the current mini-transaction to the data protected by the
182
cursor latch, as then the latch must not be released until mtr_commit. */
185
btr_pcur_release_leaf(
186
/*==================*/
187
btr_pcur_t* cursor, /* in: persistent cursor */
188
mtr_t* mtr); /* in: mtr */
189
/*************************************************************
190
Gets the rel_pos field for a cursor whose position has been stored. */
193
btr_pcur_get_rel_pos(
194
/*=================*/
195
/* out: BTR_PCUR_ON, ... */
196
btr_pcur_t* cursor);/* in: persistent cursor */
197
/******************************************************************
198
Restores the stored position of a persistent cursor bufferfixing the page and
199
obtaining the specified latches. If the cursor position was saved when the
200
(1) cursor was positioned on a user record: this function restores the position
201
to the last record LESS OR EQUAL to the stored record;
202
(2) cursor was positioned on a page infimum record: restores the position to
203
the last record LESS than the user record which was the successor of the page
205
(3) cursor was positioned on the page supremum: restores to the first record
206
GREATER than the user record which was the predecessor of the supremum. */
209
btr_pcur_restore_position(
210
/*======================*/
211
/* out: TRUE if the cursor position
212
was stored when it was on a user record
213
and it can be restored on a user record
214
whose ordering fields are identical to
215
the ones of the original user record */
216
ulint latch_mode, /* in: BTR_SEARCH_LEAF, ... */
217
btr_pcur_t* cursor, /* in: detached persistent cursor */
218
mtr_t* mtr); /* in: mtr */
219
/*************************************************************
220
Sets the mtr field for a pcur. */
225
btr_pcur_t* cursor, /* in: persistent cursor */
226
mtr_t* mtr); /* in, own: mtr */
227
/*************************************************************
228
Gets the mtr field for a pcur. */
234
btr_pcur_t* cursor); /* in: persistent cursor */
235
/******************************************************************
236
Commits the pcur mtr and sets the pcur latch mode to BTR_NO_LATCHES,
237
that is, the cursor becomes detached. If there have been modifications
238
to the page where pcur is positioned, this can be used instead of
239
btr_pcur_release_leaf. Function btr_pcur_store_position should be used
240
before calling this, if restoration of cursor is wanted later. */
245
btr_pcur_t* pcur); /* in: persistent cursor */
246
/******************************************************************
247
Differs from btr_pcur_commit in that we can specify the mtr to commit. */
250
btr_pcur_commit_specify_mtr(
251
/*========================*/
252
btr_pcur_t* pcur, /* in: persistent cursor */
253
mtr_t* mtr); /* in: mtr to commit */
254
/******************************************************************
255
Tests if a cursor is detached: that is the latch mode is BTR_NO_LATCHES. */
258
btr_pcur_is_detached(
259
/*=================*/
260
/* out: TRUE if detached */
261
btr_pcur_t* pcur); /* in: persistent cursor */
262
/*************************************************************
263
Moves the persistent cursor to the next record in the tree. If no records are
264
left, the cursor stays 'after last in tree'. */
267
btr_pcur_move_to_next(
268
/*==================*/
269
/* out: TRUE if the cursor was not after last
271
btr_pcur_t* cursor, /* in: persistent cursor; NOTE that the
272
function may release the page latch */
273
mtr_t* mtr); /* in: mtr */
274
/*************************************************************
275
Moves the persistent cursor to the previous record in the tree. If no records
276
are left, the cursor stays 'before first in tree'. */
279
btr_pcur_move_to_prev(
280
/*==================*/
281
/* out: TRUE if the cursor was not before first
283
btr_pcur_t* cursor, /* in: persistent cursor; NOTE that the
284
function may release the page latch */
285
mtr_t* mtr); /* in: mtr */
286
/*************************************************************
287
Moves the persistent cursor to the next user record in the tree. If no user
288
records are left, the cursor ends up 'after last in tree'. */
291
btr_pcur_move_to_next_user_rec(
292
/*===========================*/
293
/* out: TRUE if the cursor moved forward,
294
ending on a user record */
295
btr_pcur_t* cursor, /* in: persistent cursor; NOTE that the
296
function may release the page latch */
297
mtr_t* mtr); /* in: mtr */
298
/*************************************************************
299
Moves the persistent cursor to the first record on the next page.
300
Releases the latch on the current page, and bufferunfixes it.
301
Note that there must not be modifications on the current page,
302
as then the x-latch can be released only in mtr_commit. */
305
btr_pcur_move_to_next_page(
306
/*=======================*/
307
btr_pcur_t* cursor, /* in: persistent cursor; must be on the
308
last record of the current page */
309
mtr_t* mtr); /* in: mtr */
310
/*************************************************************
311
Moves the persistent cursor backward if it is on the first record
312
of the page. Releases the latch on the current page, and bufferunfixes
313
it. Note that to prevent a possible deadlock, the operation first
314
stores the position of the cursor, releases the leaf latch, acquires
315
necessary latches and restores the cursor position again before returning.
316
The alphabetical position of the cursor is guaranteed to be sensible
317
on return, but it may happen that the cursor is not positioned on the
318
last record of any page, because the structure of the tree may have
319
changed while the cursor had no latches. */
322
btr_pcur_move_backward_from_page(
323
/*=============================*/
324
btr_pcur_t* cursor, /* in: persistent cursor, must be on the
325
first record of the current page */
326
mtr_t* mtr); /* in: mtr */
327
/*************************************************************
328
Returns the btr cursor component of a persistent cursor. */
331
btr_pcur_get_btr_cur(
332
/*=================*/
333
/* out: pointer to btr cursor component */
334
btr_pcur_t* cursor); /* in: persistent cursor */
335
/*************************************************************
336
Returns the page cursor component of a persistent cursor. */
339
btr_pcur_get_page_cur(
340
/*==================*/
341
/* out: pointer to page cursor component */
342
btr_pcur_t* cursor); /* in: persistent cursor */
343
/*************************************************************
344
Returns the page of a persistent cursor. */
349
/* out: pointer to the page */
350
btr_pcur_t* cursor);/* in: persistent cursor */
351
/*************************************************************
352
Returns the record of a persistent cursor. */
357
/* out: pointer to the record */
358
btr_pcur_t* cursor);/* in: persistent cursor */
359
/*************************************************************
360
Checks if the persistent cursor is on a user record. */
363
btr_pcur_is_on_user_rec(
364
/*====================*/
365
btr_pcur_t* cursor, /* in: persistent cursor */
366
mtr_t* mtr); /* in: mtr */
367
/*************************************************************
368
Checks if the persistent cursor is after the last user record on
372
btr_pcur_is_after_last_on_page(
373
/*===========================*/
374
btr_pcur_t* cursor, /* in: persistent cursor */
375
mtr_t* mtr); /* in: mtr */
376
/*************************************************************
377
Checks if the persistent cursor is before the first user record on
381
btr_pcur_is_before_first_on_page(
382
/*=============================*/
383
btr_pcur_t* cursor, /* in: persistent cursor */
384
mtr_t* mtr); /* in: mtr */
385
/*************************************************************
386
Checks if the persistent cursor is before the first user record in
390
btr_pcur_is_before_first_in_tree(
391
/*=============================*/
392
btr_pcur_t* cursor, /* in: persistent cursor */
393
mtr_t* mtr); /* in: mtr */
394
/*************************************************************
395
Checks if the persistent cursor is after the last user record in
399
btr_pcur_is_after_last_in_tree(
400
/*===========================*/
401
btr_pcur_t* cursor, /* in: persistent cursor */
402
mtr_t* mtr); /* in: mtr */
403
/*************************************************************
404
Moves the persistent cursor to the next record on the same page. */
407
btr_pcur_move_to_next_on_page(
408
/*==========================*/
409
btr_pcur_t* cursor, /* in: persistent cursor */
410
mtr_t* mtr); /* in: mtr */
411
/*************************************************************
412
Moves the persistent cursor to the previous record on the same page. */
415
btr_pcur_move_to_prev_on_page(
416
/*==========================*/
417
btr_pcur_t* cursor, /* in: persistent cursor */
418
mtr_t* mtr); /* in: mtr */
421
/* The persistent B-tree cursor structure. This is used mainly for SQL
422
selects, updates, and deletes. */
424
struct btr_pcur_struct{
425
btr_cur_t btr_cur; /* a B-tree cursor */
426
ulint latch_mode; /* see FIXME note below!
427
BTR_SEARCH_LEAF, BTR_MODIFY_LEAF,
428
BTR_MODIFY_TREE, or BTR_NO_LATCHES,
429
depending on the latching state of
430
the page and tree where the cursor is
431
positioned; the last value means that
432
the cursor is not currently positioned:
433
we say then that the cursor is
434
detached; it can be restored to
435
attached if the old position was
437
ulint old_stored; /* BTR_PCUR_OLD_STORED
438
or BTR_PCUR_OLD_NOT_STORED */
439
rec_t* old_rec; /* if cursor position is stored,
440
contains an initial segment of the
441
latest record cursor was positioned
442
either on, before, or after */
443
ulint rel_pos; /* BTR_PCUR_ON, BTR_PCUR_BEFORE, or
444
BTR_PCUR_AFTER, depending on whether
445
cursor was on, before, or after the
447
dulint modify_clock; /* the modify clock value of the
448
buffer block when the cursor position
450
ulint pos_state; /* see FIXME note below!
451
BTR_PCUR_IS_POSITIONED,
452
BTR_PCUR_WAS_POSITIONED,
453
BTR_PCUR_NOT_POSITIONED */
454
ulint search_mode; /* PAGE_CUR_G, ... */
455
/*-----------------------------*/
456
/* NOTE that the following fields may possess dynamically allocated
457
memory, which should be freed if not needed anymore! */
459
mtr_t* mtr; /* NULL, or this field may contain
460
a mini-transaction which holds the
461
latch on the cursor page */
462
byte* old_rec_buf; /* NULL, or a dynamically allocated
463
buffer for old_rec */
464
ulint buf_size; /* old_rec_buf size if old_rec_buf
468
#define BTR_PCUR_IS_POSITIONED 1997660512 /* FIXME: currently, the state
469
can be BTR_PCUR_IS_POSITIONED,
470
though it really should be
471
BTR_PCUR_WAS_POSITIONED,
472
because we have no obligation
473
to commit the cursor with
474
mtr; similarly latch_mode may
476
#define BTR_PCUR_WAS_POSITIONED 1187549791
477
#define BTR_PCUR_NOT_POSITIONED 1328997689
479
#define BTR_PCUR_OLD_STORED 908467085
480
#define BTR_PCUR_OLD_NOT_STORED 122766467
483
#include "btr0pcur.ic"