1
by brian
clean slate |
1 |
/******************************************************
|
2 |
The index tree cursor
|
|
3 |
||
4 |
(c) 1994-1996 Innobase Oy
|
|
5 |
||
6 |
Created 10/16/1994 Heikki Tuuri
|
|
7 |
*******************************************************/
|
|
8 |
||
9 |
#ifndef btr0cur_h
|
|
10 |
#define btr0cur_h
|
|
11 |
||
12 |
#include "univ.i" |
|
13 |
#include "dict0dict.h" |
|
14 |
#include "data0data.h" |
|
15 |
#include "page0cur.h" |
|
16 |
#include "btr0types.h" |
|
17 |
#include "que0types.h" |
|
18 |
#include "row0types.h" |
|
19 |
#include "ha0ha.h" |
|
20 |
||
21 |
/* Mode flags for btr_cur operations; these can be ORed */
|
|
22 |
#define BTR_NO_UNDO_LOG_FLAG 1 /* do no undo logging */ |
|
23 |
#define BTR_NO_LOCKING_FLAG 2 /* do no record lock checking */ |
|
24 |
#define BTR_KEEP_SYS_FLAG 4 /* sys fields will be found from the |
|
25 |
update vector or inserted entry */
|
|
26 |
||
27 |
#define BTR_CUR_ADAPT
|
|
28 |
#define BTR_CUR_HASH_ADAPT
|
|
29 |
||
30 |
/*************************************************************
|
|
31 |
Returns the page cursor component of a tree cursor. */
|
|
32 |
UNIV_INLINE
|
|
33 |
page_cur_t* |
|
34 |
btr_cur_get_page_cur( |
|
35 |
/*=================*/
|
|
36 |
/* out: pointer to page cursor component */
|
|
37 |
btr_cur_t* cursor);/* in: tree cursor */ |
|
38 |
/*************************************************************
|
|
39 |
Returns the record pointer of a tree cursor. */
|
|
40 |
UNIV_INLINE
|
|
41 |
rec_t* |
|
42 |
btr_cur_get_rec( |
|
43 |
/*============*/
|
|
44 |
/* out: pointer to record */
|
|
45 |
btr_cur_t* cursor);/* in: tree cursor */ |
|
46 |
/*************************************************************
|
|
47 |
Invalidates a tree cursor by setting record pointer to NULL. */
|
|
48 |
UNIV_INLINE
|
|
49 |
void
|
|
50 |
btr_cur_invalidate( |
|
51 |
/*===============*/
|
|
52 |
btr_cur_t* cursor);/* in: tree cursor */ |
|
53 |
/*************************************************************
|
|
54 |
Returns the page of a tree cursor. */
|
|
55 |
UNIV_INLINE
|
|
56 |
page_t* |
|
57 |
btr_cur_get_page( |
|
58 |
/*=============*/
|
|
59 |
/* out: pointer to page */
|
|
60 |
btr_cur_t* cursor);/* in: tree cursor */ |
|
61 |
/*************************************************************
|
|
62 |
Returns the index of a cursor. */
|
|
63 |
UNIV_INLINE
|
|
64 |
dict_index_t* |
|
65 |
btr_cur_get_index( |
|
66 |
/*==============*/
|
|
67 |
/* out: index */
|
|
68 |
btr_cur_t* cursor);/* in: B-tree cursor */ |
|
69 |
/*************************************************************
|
|
70 |
Positions a tree cursor at a given record. */
|
|
71 |
UNIV_INLINE
|
|
72 |
void
|
|
73 |
btr_cur_position( |
|
74 |
/*=============*/
|
|
75 |
dict_index_t* index, /* in: index */ |
|
76 |
rec_t* rec, /* in: record in tree */ |
|
77 |
btr_cur_t* cursor);/* in: cursor */ |
|
78 |
/************************************************************************
|
|
79 |
Searches an index tree and positions a tree cursor on a given level.
|
|
80 |
NOTE: n_fields_cmp in tuple must be set so that it cannot be compared
|
|
81 |
to node pointer page number fields on the upper levels of the tree!
|
|
82 |
Note that if mode is PAGE_CUR_LE, which is used in inserts, then
|
|
83 |
cursor->up_match and cursor->low_match both will have sensible values.
|
|
84 |
If mode is PAGE_CUR_GE, then up_match will a have a sensible value. */
|
|
85 |
||
86 |
void
|
|
87 |
btr_cur_search_to_nth_level( |
|
88 |
/*========================*/
|
|
89 |
dict_index_t* index, /* in: index */ |
|
90 |
ulint level, /* in: the tree level of search */ |
|
91 |
dtuple_t* tuple, /* in: data tuple; NOTE: n_fields_cmp in |
|
92 |
tuple must be set so that it cannot get
|
|
93 |
compared to the node ptr page number field! */
|
|
94 |
ulint mode, /* in: PAGE_CUR_L, ...; |
|
95 |
NOTE that if the search is made using a unique
|
|
96 |
prefix of a record, mode should be PAGE_CUR_LE,
|
|
97 |
not PAGE_CUR_GE, as the latter may end up on
|
|
98 |
the previous page of the record! Inserts
|
|
99 |
should always be made using PAGE_CUR_LE to
|
|
100 |
search the position! */
|
|
101 |
ulint latch_mode, /* in: BTR_SEARCH_LEAF, ..., ORed with |
|
102 |
BTR_INSERT and BTR_ESTIMATE;
|
|
103 |
cursor->left_page is used to store a pointer
|
|
104 |
to the left neighbor page, in the cases
|
|
105 |
BTR_SEARCH_PREV and BTR_MODIFY_PREV;
|
|
106 |
NOTE that if has_search_latch
|
|
107 |
is != 0, we maybe do not have a latch set
|
|
108 |
on the cursor page, we assume
|
|
109 |
the caller uses his search latch
|
|
110 |
to protect the record! */
|
|
111 |
btr_cur_t* cursor, /* in/out: tree cursor; the cursor page is |
|
112 |
s- or x-latched, but see also above! */
|
|
113 |
ulint has_search_latch,/* in: latch mode the caller |
|
114 |
currently has on btr_search_latch:
|
|
115 |
RW_S_LATCH, or 0 */
|
|
116 |
mtr_t* mtr); /* in: mtr */ |
|
117 |
/*********************************************************************
|
|
118 |
Opens a cursor at either end of an index. */
|
|
119 |
||
120 |
void
|
|
121 |
btr_cur_open_at_index_side( |
|
122 |
/*=======================*/
|
|
123 |
ibool from_left, /* in: TRUE if open to the low end, |
|
124 |
FALSE if to the high end */
|
|
125 |
dict_index_t* index, /* in: index */ |
|
126 |
ulint latch_mode, /* in: latch mode */ |
|
127 |
btr_cur_t* cursor, /* in: cursor */ |
|
128 |
mtr_t* mtr); /* in: mtr */ |
|
129 |
/**************************************************************************
|
|
130 |
Positions a cursor at a randomly chosen position within a B-tree. */
|
|
131 |
||
132 |
void
|
|
133 |
btr_cur_open_at_rnd_pos( |
|
134 |
/*====================*/
|
|
135 |
dict_index_t* index, /* in: index */ |
|
136 |
ulint latch_mode, /* in: BTR_SEARCH_LEAF, ... */ |
|
137 |
btr_cur_t* cursor, /* in/out: B-tree cursor */ |
|
138 |
mtr_t* mtr); /* in: mtr */ |
|
139 |
/*****************************************************************
|
|
140 |
Tries to perform an insert to a page in an index tree, next to cursor.
|
|
141 |
It is assumed that mtr holds an x-latch on the page. The operation does
|
|
142 |
not succeed if there is too little space on the page. If there is just
|
|
143 |
one record on the page, the insert will always succeed; this is to
|
|
144 |
prevent trying to split a page with just one record. */
|
|
145 |
||
146 |
ulint
|
|
147 |
btr_cur_optimistic_insert( |
|
148 |
/*======================*/
|
|
149 |
/* out: DB_SUCCESS, DB_WAIT_LOCK,
|
|
150 |
DB_FAIL, or error number */
|
|
151 |
ulint flags, /* in: undo logging and locking flags: if not |
|
152 |
zero, the parameters index and thr should be
|
|
153 |
specified */
|
|
154 |
btr_cur_t* cursor, /* in: cursor on page after which to insert; |
|
155 |
cursor stays valid */
|
|
156 |
dtuple_t* entry, /* in: entry to insert */ |
|
157 |
rec_t** rec, /* out: pointer to inserted record if |
|
158 |
succeed */
|
|
159 |
big_rec_t** big_rec,/* out: big rec vector whose fields have to |
|
160 |
be stored externally by the caller, or
|
|
161 |
NULL */
|
|
162 |
que_thr_t* thr, /* in: query thread or NULL */ |
|
163 |
mtr_t* mtr); /* in: mtr */ |
|
164 |
/*****************************************************************
|
|
165 |
Performs an insert on a page of an index tree. It is assumed that mtr
|
|
166 |
holds an x-latch on the tree and on the cursor page. If the insert is
|
|
167 |
made on the leaf level, to avoid deadlocks, mtr must also own x-latches
|
|
168 |
to brothers of page, if those brothers exist. */
|
|
169 |
||
170 |
ulint
|
|
171 |
btr_cur_pessimistic_insert( |
|
172 |
/*=======================*/
|
|
173 |
/* out: DB_SUCCESS or error number */
|
|
174 |
ulint flags, /* in: undo logging and locking flags: if not |
|
175 |
zero, the parameter thr should be
|
|
176 |
specified; if no undo logging is specified,
|
|
177 |
then the caller must have reserved enough
|
|
178 |
free extents in the file space so that the
|
|
179 |
insertion will certainly succeed */
|
|
180 |
btr_cur_t* cursor, /* in: cursor after which to insert; |
|
181 |
cursor stays valid */
|
|
182 |
dtuple_t* entry, /* in: entry to insert */ |
|
183 |
rec_t** rec, /* out: pointer to inserted record if |
|
184 |
succeed */
|
|
185 |
big_rec_t** big_rec,/* out: big rec vector whose fields have to |
|
186 |
be stored externally by the caller, or
|
|
187 |
NULL */
|
|
188 |
que_thr_t* thr, /* in: query thread or NULL */ |
|
189 |
mtr_t* mtr); /* in: mtr */ |
|
190 |
/*****************************************************************
|
|
191 |
Updates a record when the update causes no size changes in its fields. */
|
|
192 |
||
193 |
ulint
|
|
194 |
btr_cur_update_in_place( |
|
195 |
/*====================*/
|
|
196 |
/* out: DB_SUCCESS or error number */
|
|
197 |
ulint flags, /* in: undo logging and locking flags */ |
|
198 |
btr_cur_t* cursor, /* in: cursor on the record to update; |
|
199 |
cursor stays valid and positioned on the
|
|
200 |
same record */
|
|
201 |
upd_t* update, /* in: update vector */ |
|
202 |
ulint cmpl_info,/* in: compiler info on secondary index |
|
203 |
updates */
|
|
204 |
que_thr_t* thr, /* in: query thread */ |
|
205 |
mtr_t* mtr); /* in: mtr */ |
|
206 |
/*****************************************************************
|
|
207 |
Tries to update a record on a page in an index tree. It is assumed that mtr
|
|
208 |
holds an x-latch on the page. The operation does not succeed if there is too
|
|
209 |
little space on the page or if the update would result in too empty a page,
|
|
210 |
so that tree compression is recommended. */
|
|
211 |
||
212 |
ulint
|
|
213 |
btr_cur_optimistic_update( |
|
214 |
/*======================*/
|
|
215 |
/* out: DB_SUCCESS, or DB_OVERFLOW if the
|
|
216 |
updated record does not fit, DB_UNDERFLOW
|
|
217 |
if the page would become too empty */
|
|
218 |
ulint flags, /* in: undo logging and locking flags */ |
|
219 |
btr_cur_t* cursor, /* in: cursor on the record to update; |
|
220 |
cursor stays valid and positioned on the
|
|
221 |
same record */
|
|
222 |
upd_t* update, /* in: update vector; this must also |
|
223 |
contain trx id and roll ptr fields */
|
|
224 |
ulint cmpl_info,/* in: compiler info on secondary index |
|
225 |
updates */
|
|
226 |
que_thr_t* thr, /* in: query thread */ |
|
227 |
mtr_t* mtr); /* in: mtr */ |
|
228 |
/*****************************************************************
|
|
229 |
Performs an update of a record on a page of a tree. It is assumed
|
|
230 |
that mtr holds an x-latch on the tree and on the cursor page. If the
|
|
231 |
update is made on the leaf level, to avoid deadlocks, mtr must also
|
|
232 |
own x-latches to brothers of page, if those brothers exist. */
|
|
233 |
||
234 |
ulint
|
|
235 |
btr_cur_pessimistic_update( |
|
236 |
/*=======================*/
|
|
237 |
/* out: DB_SUCCESS or error code */
|
|
238 |
ulint flags, /* in: undo logging, locking, and rollback |
|
239 |
flags */
|
|
240 |
btr_cur_t* cursor, /* in: cursor on the record to update */ |
|
241 |
big_rec_t** big_rec,/* out: big rec vector whose fields have to |
|
242 |
be stored externally by the caller, or NULL */
|
|
243 |
upd_t* update, /* in: update vector; this is allowed also |
|
244 |
contain trx id and roll ptr fields, but
|
|
245 |
the values in update vector have no effect */
|
|
246 |
ulint cmpl_info,/* in: compiler info on secondary index |
|
247 |
updates */
|
|
248 |
que_thr_t* thr, /* in: query thread */ |
|
249 |
mtr_t* mtr); /* in: mtr */ |
|
250 |
/***************************************************************
|
|
251 |
Marks a clustered index record deleted. Writes an undo log record to
|
|
252 |
undo log on this delete marking. Writes in the trx id field the id
|
|
253 |
of the deleting transaction, and in the roll ptr field pointer to the
|
|
254 |
undo log record created. */
|
|
255 |
||
256 |
ulint
|
|
257 |
btr_cur_del_mark_set_clust_rec( |
|
258 |
/*===========================*/
|
|
259 |
/* out: DB_SUCCESS, DB_LOCK_WAIT, or error
|
|
260 |
number */
|
|
261 |
ulint flags, /* in: undo logging and locking flags */ |
|
262 |
btr_cur_t* cursor, /* in: cursor */ |
|
263 |
ibool val, /* in: value to set */ |
|
264 |
que_thr_t* thr, /* in: query thread */ |
|
265 |
mtr_t* mtr); /* in: mtr */ |
|
266 |
/***************************************************************
|
|
267 |
Sets a secondary index record delete mark to TRUE or FALSE. */
|
|
268 |
||
269 |
ulint
|
|
270 |
btr_cur_del_mark_set_sec_rec( |
|
271 |
/*=========================*/
|
|
272 |
/* out: DB_SUCCESS, DB_LOCK_WAIT, or error
|
|
273 |
number */
|
|
274 |
ulint flags, /* in: locking flag */ |
|
275 |
btr_cur_t* cursor, /* in: cursor */ |
|
276 |
ibool val, /* in: value to set */ |
|
277 |
que_thr_t* thr, /* in: query thread */ |
|
278 |
mtr_t* mtr); /* in: mtr */ |
|
279 |
/***************************************************************
|
|
280 |
Sets a secondary index record delete mark to FALSE. This function is
|
|
281 |
only used by the insert buffer insert merge mechanism. */
|
|
282 |
||
283 |
void
|
|
284 |
btr_cur_del_unmark_for_ibuf( |
|
285 |
/*========================*/
|
|
286 |
rec_t* rec, /* in: record to delete unmark */ |
|
287 |
mtr_t* mtr); /* in: mtr */ |
|
288 |
/*****************************************************************
|
|
289 |
Tries to compress a page of the tree on the leaf level. It is assumed
|
|
290 |
that mtr holds an x-latch on the tree and on the cursor page. To avoid
|
|
291 |
deadlocks, mtr must also own x-latches to brothers of page, if those
|
|
292 |
brothers exist. NOTE: it is assumed that the caller has reserved enough
|
|
293 |
free extents so that the compression will always succeed if done! */
|
|
294 |
||
295 |
void
|
|
296 |
btr_cur_compress( |
|
297 |
/*=============*/
|
|
298 |
btr_cur_t* cursor, /* in: cursor on the page to compress; |
|
299 |
cursor does not stay valid */
|
|
300 |
mtr_t* mtr); /* in: mtr */ |
|
301 |
/*****************************************************************
|
|
302 |
Tries to compress a page of the tree if it seems useful. It is assumed
|
|
303 |
that mtr holds an x-latch on the tree and on the cursor page. To avoid
|
|
304 |
deadlocks, mtr must also own x-latches to brothers of page, if those
|
|
305 |
brothers exist. NOTE: it is assumed that the caller has reserved enough
|
|
306 |
free extents so that the compression will always succeed if done! */
|
|
307 |
||
308 |
ibool
|
|
309 |
btr_cur_compress_if_useful( |
|
310 |
/*=======================*/
|
|
311 |
/* out: TRUE if compression occurred */
|
|
312 |
btr_cur_t* cursor, /* in: cursor on the page to compress; |
|
313 |
cursor does not stay valid if compression
|
|
314 |
occurs */
|
|
315 |
mtr_t* mtr); /* in: mtr */ |
|
316 |
/***********************************************************
|
|
317 |
Removes the record on which the tree cursor is positioned. It is assumed
|
|
318 |
that the mtr has an x-latch on the page where the cursor is positioned,
|
|
319 |
but no latch on the whole tree. */
|
|
320 |
||
321 |
ibool
|
|
322 |
btr_cur_optimistic_delete( |
|
323 |
/*======================*/
|
|
324 |
/* out: TRUE if success, i.e., the page
|
|
325 |
did not become too empty */
|
|
326 |
btr_cur_t* cursor, /* in: cursor on the record to delete; |
|
327 |
cursor stays valid: if deletion succeeds,
|
|
328 |
on function exit it points to the successor
|
|
329 |
of the deleted record */
|
|
330 |
mtr_t* mtr); /* in: mtr */ |
|
331 |
/*****************************************************************
|
|
332 |
Removes the record on which the tree cursor is positioned. Tries
|
|
333 |
to compress the page if its fillfactor drops below a threshold
|
|
334 |
or if it is the only page on the level. It is assumed that mtr holds
|
|
335 |
an x-latch on the tree and on the cursor page. To avoid deadlocks,
|
|
336 |
mtr must also own x-latches to brothers of page, if those brothers
|
|
337 |
exist. */
|
|
338 |
||
339 |
ibool
|
|
340 |
btr_cur_pessimistic_delete( |
|
341 |
/*=======================*/
|
|
342 |
/* out: TRUE if compression occurred */
|
|
343 |
ulint* err, /* out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE; |
|
344 |
the latter may occur because we may have
|
|
345 |
to update node pointers on upper levels,
|
|
346 |
and in the case of variable length keys
|
|
347 |
these may actually grow in size */
|
|
348 |
ibool has_reserved_extents, /* in: TRUE if the |
|
349 |
caller has already reserved enough free
|
|
350 |
extents so that he knows that the operation
|
|
351 |
will succeed */
|
|
352 |
btr_cur_t* cursor, /* in: cursor on the record to delete; |
|
353 |
if compression does not occur, the cursor
|
|
354 |
stays valid: it points to successor of
|
|
355 |
deleted record on function exit */
|
|
356 |
ibool in_rollback,/* in: TRUE if called in rollback */ |
|
357 |
mtr_t* mtr); /* in: mtr */ |
|
358 |
/***************************************************************
|
|
359 |
Parses a redo log record of updating a record in-place. */
|
|
360 |
||
361 |
byte* |
|
362 |
btr_cur_parse_update_in_place( |
|
363 |
/*==========================*/
|
|
364 |
/* out: end of log record or NULL */
|
|
365 |
byte* ptr, /* in: buffer */ |
|
366 |
byte* end_ptr,/* in: buffer end */ |
|
367 |
page_t* page, /* in: page or NULL */ |
|
368 |
dict_index_t* index); /* in: index corresponding to page */ |
|
369 |
/********************************************************************
|
|
370 |
Parses the redo log record for delete marking or unmarking of a clustered
|
|
371 |
index record. */
|
|
372 |
||
373 |
byte* |
|
374 |
btr_cur_parse_del_mark_set_clust_rec( |
|
375 |
/*=================================*/
|
|
376 |
/* out: end of log record or NULL */
|
|
377 |
byte* ptr, /* in: buffer */ |
|
378 |
byte* end_ptr,/* in: buffer end */ |
|
379 |
dict_index_t* index, /* in: index corresponding to page */ |
|
380 |
page_t* page); /* in: page or NULL */ |
|
381 |
/********************************************************************
|
|
382 |
Parses the redo log record for delete marking or unmarking of a secondary
|
|
383 |
index record. */
|
|
384 |
||
385 |
byte* |
|
386 |
btr_cur_parse_del_mark_set_sec_rec( |
|
387 |
/*===============================*/
|
|
388 |
/* out: end of log record or NULL */
|
|
389 |
byte* ptr, /* in: buffer */ |
|
390 |
byte* end_ptr,/* in: buffer end */ |
|
391 |
page_t* page); /* in: page or NULL */ |
|
392 |
/***********************************************************************
|
|
393 |
Estimates the number of rows in a given index range. */
|
|
394 |
||
395 |
ib_longlong
|
|
396 |
btr_estimate_n_rows_in_range( |
|
397 |
/*=========================*/
|
|
398 |
/* out: estimated number of rows */
|
|
399 |
dict_index_t* index, /* in: index */ |
|
400 |
dtuple_t* tuple1, /* in: range start, may also be empty tuple */ |
|
401 |
ulint mode1, /* in: search mode for range start */ |
|
402 |
dtuple_t* tuple2, /* in: range end, may also be empty tuple */ |
|
403 |
ulint mode2); /* in: search mode for range end */ |
|
404 |
/***********************************************************************
|
|
405 |
Estimates the number of different key values in a given index, for
|
|
406 |
each n-column prefix of the index where n <= dict_index_get_n_unique(index).
|
|
407 |
The estimates are stored in the array index->stat_n_diff_key_vals. */
|
|
408 |
||
409 |
void
|
|
410 |
btr_estimate_number_of_different_key_vals( |
|
411 |
/*======================================*/
|
|
412 |
dict_index_t* index); /* in: index */ |
|
413 |
/***********************************************************************
|
|
414 |
Marks not updated extern fields as not-owned by this record. The ownership
|
|
415 |
is transferred to the updated record which is inserted elsewhere in the
|
|
416 |
index tree. In purge only the owner of externally stored field is allowed
|
|
417 |
to free the field. */
|
|
418 |
||
419 |
void
|
|
420 |
btr_cur_mark_extern_inherited_fields( |
|
421 |
/*=================================*/
|
|
422 |
rec_t* rec, /* in: record in a clustered index */ |
|
423 |
const ulint* offsets,/* in: array returned by rec_get_offsets() */ |
|
424 |
upd_t* update, /* in: update vector */ |
|
425 |
mtr_t* mtr); /* in: mtr */ |
|
426 |
/***********************************************************************
|
|
427 |
The complement of the previous function: in an update entry may inherit
|
|
428 |
some externally stored fields from a record. We must mark them as inherited
|
|
429 |
in entry, so that they are not freed in a rollback. */
|
|
430 |
||
431 |
void
|
|
432 |
btr_cur_mark_dtuple_inherited_extern( |
|
433 |
/*=================================*/
|
|
434 |
dtuple_t* entry, /* in: updated entry to be inserted to |
|
435 |
clustered index */
|
|
436 |
ulint* ext_vec, /* in: array of extern fields in the |
|
437 |
original record */
|
|
438 |
ulint n_ext_vec, /* in: number of elements in ext_vec */ |
|
439 |
upd_t* update); /* in: update vector */ |
|
440 |
/***********************************************************************
|
|
441 |
Marks all extern fields in a dtuple as owned by the record. */
|
|
442 |
||
443 |
void
|
|
444 |
btr_cur_unmark_dtuple_extern_fields( |
|
445 |
/*================================*/
|
|
446 |
dtuple_t* entry, /* in: clustered index entry */ |
|
447 |
ulint* ext_vec, /* in: array of numbers of fields |
|
448 |
which have been stored externally */
|
|
449 |
ulint n_ext_vec); /* in: number of elements in ext_vec */ |
|
450 |
/***********************************************************************
|
|
451 |
Stores the fields in big_rec_vec to the tablespace and puts pointers to
|
|
452 |
them in rec. The fields are stored on pages allocated from leaf node
|
|
453 |
file segment of the index tree. */
|
|
454 |
||
455 |
ulint
|
|
456 |
btr_store_big_rec_extern_fields( |
|
457 |
/*============================*/
|
|
458 |
/* out: DB_SUCCESS or error */
|
|
459 |
dict_index_t* index, /* in: index of rec; the index tree |
|
460 |
MUST be X-latched */
|
|
461 |
rec_t* rec, /* in: record */ |
|
462 |
const ulint* offsets, /* in: rec_get_offsets(rec, index); |
|
463 |
the "external storage" flags in offsets
|
|
464 |
will not correspond to rec when
|
|
465 |
this function returns */
|
|
466 |
big_rec_t* big_rec_vec, /* in: vector containing fields |
|
467 |
to be stored externally */
|
|
468 |
mtr_t* local_mtr); /* in: mtr containing the latch to |
|
469 |
rec and to the tree */
|
|
470 |
/***********************************************************************
|
|
471 |
Frees the space in an externally stored field to the file space
|
|
472 |
management if the field in data is owned the externally stored field,
|
|
473 |
in a rollback we may have the additional condition that the field must
|
|
474 |
not be inherited. */
|
|
475 |
||
476 |
void
|
|
477 |
btr_free_externally_stored_field( |
|
478 |
/*=============================*/
|
|
479 |
dict_index_t* index, /* in: index of the data, the index |
|
480 |
tree MUST be X-latched; if the tree
|
|
481 |
height is 1, then also the root page
|
|
482 |
must be X-latched! (this is relevant
|
|
483 |
in the case this function is called
|
|
484 |
from purge where 'data' is located on
|
|
485 |
an undo log page, not an index
|
|
486 |
page) */
|
|
487 |
byte* data, /* in: internally stored data |
|
488 |
+ reference to the externally
|
|
489 |
stored part */
|
|
490 |
ulint local_len, /* in: length of data */ |
|
491 |
ibool do_not_free_inherited,/* in: TRUE if called in a |
|
492 |
rollback and we do not want to free
|
|
493 |
inherited fields */
|
|
494 |
mtr_t* local_mtr); /* in: mtr containing the latch to |
|
495 |
data an an X-latch to the index
|
|
496 |
tree */
|
|
497 |
/***************************************************************
|
|
498 |
Frees the externally stored fields for a record. */
|
|
499 |
||
500 |
void
|
|
501 |
btr_rec_free_externally_stored_fields( |
|
502 |
/*==================================*/
|
|
503 |
dict_index_t* index, /* in: index of the data, the index |
|
504 |
tree MUST be X-latched */
|
|
505 |
rec_t* rec, /* in: record */ |
|
506 |
const ulint* offsets,/* in: rec_get_offsets(rec, index) */ |
|
507 |
ibool do_not_free_inherited,/* in: TRUE if called in a |
|
508 |
rollback and we do not want to free
|
|
509 |
inherited fields */
|
|
510 |
mtr_t* mtr); /* in: mini-transaction handle which contains |
|
511 |
an X-latch to record page and to the index
|
|
512 |
tree */
|
|
513 |
/***********************************************************************
|
|
514 |
Copies an externally stored field of a record to mem heap. */
|
|
515 |
||
516 |
byte* |
|
517 |
btr_rec_copy_externally_stored_field( |
|
518 |
/*=================================*/
|
|
519 |
/* out: the field copied to heap */
|
|
520 |
rec_t* rec, /* in: record */ |
|
521 |
const ulint* offsets,/* in: array returned by rec_get_offsets() */ |
|
522 |
ulint no, /* in: field number */ |
|
523 |
ulint* len, /* out: length of the field */ |
|
524 |
mem_heap_t* heap); /* in: mem heap */ |
|
525 |
/***********************************************************************
|
|
526 |
Copies an externally stored field of a record to mem heap. Parameter
|
|
527 |
data contains a pointer to 'internally' stored part of the field:
|
|
528 |
possibly some data, and the reference to the externally stored part in
|
|
529 |
the last 20 bytes of data. */
|
|
530 |
||
531 |
byte* |
|
532 |
btr_copy_externally_stored_field( |
|
533 |
/*=============================*/
|
|
534 |
/* out: the whole field copied to heap */
|
|
535 |
ulint* len, /* out: length of the whole field */ |
|
536 |
byte* data, /* in: 'internally' stored part of the |
|
537 |
field containing also the reference to
|
|
538 |
the external part */
|
|
539 |
ulint local_len,/* in: length of data */ |
|
540 |
mem_heap_t* heap); /* in: mem heap */ |
|
541 |
/***********************************************************************
|
|
542 |
Stores the positions of the fields marked as extern storage in the update
|
|
543 |
vector, and also those fields who are marked as extern storage in rec
|
|
544 |
and not mentioned in updated fields. We use this function to remember
|
|
545 |
which fields we must mark as extern storage in a record inserted for an
|
|
546 |
update. */
|
|
547 |
||
548 |
ulint
|
|
549 |
btr_push_update_extern_fields( |
|
550 |
/*==========================*/
|
|
551 |
/* out: number of values stored in ext_vect */
|
|
552 |
ulint* ext_vect,/* in: array of ulints, must be preallocated |
|
553 |
to have space for all fields in rec */
|
|
554 |
const ulint* offsets,/* in: array returned by rec_get_offsets() */ |
|
555 |
upd_t* update);/* in: update vector or NULL */ |
|
556 |
||
557 |
||
558 |
/*######################################################################*/
|
|
559 |
||
560 |
/* In the pessimistic delete, if the page data size drops below this
|
|
561 |
limit, merging it to a neighbor is tried */
|
|
562 |
||
563 |
#define BTR_CUR_PAGE_COMPRESS_LIMIT (UNIV_PAGE_SIZE / 2)
|
|
564 |
||
565 |
/* A slot in the path array. We store here info on a search path down the
|
|
566 |
tree. Each slot contains data on a single level of the tree. */
|
|
567 |
||
568 |
typedef struct btr_path_struct btr_path_t; |
|
569 |
struct btr_path_struct{ |
|
570 |
ulint nth_rec; /* index of the record |
|
571 |
where the page cursor stopped on
|
|
572 |
this level (index in alphabetical
|
|
573 |
order); value ULINT_UNDEFINED
|
|
574 |
denotes array end */
|
|
575 |
ulint n_recs; /* number of records on the page */ |
|
576 |
};
|
|
577 |
||
578 |
#define BTR_PATH_ARRAY_N_SLOTS 250 /* size of path array (in slots) */ |
|
579 |
||
580 |
/* The tree cursor: the definition appears here only for the compiler
|
|
581 |
to know struct size! */
|
|
582 |
||
583 |
struct btr_cur_struct { |
|
584 |
dict_index_t* index; /* index where positioned */ |
|
585 |
page_cur_t page_cur; /* page cursor */ |
|
586 |
page_t* left_page; /* this field is used to store |
|
587 |
a pointer to the left neighbor
|
|
588 |
page, in the cases
|
|
589 |
BTR_SEARCH_PREV and
|
|
590 |
BTR_MODIFY_PREV */
|
|
591 |
/*------------------------------*/
|
|
592 |
que_thr_t* thr; /* this field is only used when |
|
593 |
btr_cur_search_... is called for an
|
|
594 |
index entry insertion: the calling
|
|
595 |
query thread is passed here to be
|
|
596 |
used in the insert buffer */
|
|
597 |
/*------------------------------*/
|
|
598 |
/* The following fields are used in btr_cur_search... to pass
|
|
599 |
information: */
|
|
600 |
ulint flag; /* BTR_CUR_HASH, BTR_CUR_HASH_FAIL, |
|
601 |
BTR_CUR_BINARY, or
|
|
602 |
BTR_CUR_INSERT_TO_IBUF */
|
|
603 |
ulint tree_height; /* Tree height if the search is done |
|
604 |
for a pessimistic insert or update
|
|
605 |
operation */
|
|
606 |
ulint up_match; /* If the search mode was PAGE_CUR_LE, |
|
607 |
the number of matched fields to the
|
|
608 |
the first user record to the right of
|
|
609 |
the cursor record after
|
|
610 |
btr_cur_search_...;
|
|
611 |
for the mode PAGE_CUR_GE, the matched
|
|
612 |
fields to the first user record AT THE
|
|
613 |
CURSOR or to the right of it;
|
|
614 |
NOTE that the up_match and low_match
|
|
615 |
values may exceed the correct values
|
|
616 |
for comparison to the adjacent user
|
|
617 |
record if that record is on a
|
|
618 |
different leaf page! (See the note in
|
|
619 |
row_ins_duplicate_key.) */
|
|
620 |
ulint up_bytes; /* number of matched bytes to the |
|
621 |
right at the time cursor positioned;
|
|
622 |
only used internally in searches: not
|
|
623 |
defined after the search */
|
|
624 |
ulint low_match; /* if search mode was PAGE_CUR_LE, |
|
625 |
the number of matched fields to the
|
|
626 |
first user record AT THE CURSOR or
|
|
627 |
to the left of it after
|
|
628 |
btr_cur_search_...;
|
|
629 |
NOT defined for PAGE_CUR_GE or any
|
|
630 |
other search modes; see also the NOTE
|
|
631 |
in up_match! */
|
|
632 |
ulint low_bytes; /* number of matched bytes to the |
|
633 |
right at the time cursor positioned;
|
|
634 |
only used internally in searches: not
|
|
635 |
defined after the search */
|
|
636 |
ulint n_fields; /* prefix length used in a hash |
|
637 |
search if hash_node != NULL */
|
|
638 |
ulint n_bytes; /* hash prefix bytes if hash_node != |
|
639 |
NULL */
|
|
640 |
ulint fold; /* fold value used in the search if |
|
641 |
flag is BTR_CUR_HASH */
|
|
642 |
/*------------------------------*/
|
|
643 |
btr_path_t* path_arr; /* in estimating the number of |
|
644 |
rows in range, we store in this array
|
|
645 |
information of the path through
|
|
646 |
the tree */
|
|
647 |
};
|
|
648 |
||
649 |
/* Values for the flag documenting the used search method */
|
|
650 |
#define BTR_CUR_HASH 1 /* successful shortcut using the hash |
|
651 |
index */
|
|
652 |
#define BTR_CUR_HASH_FAIL 2 /* failure using hash, success using |
|
653 |
binary search: the misleading hash
|
|
654 |
reference is stored in the field
|
|
655 |
hash_node, and might be necessary to
|
|
656 |
update */
|
|
657 |
#define BTR_CUR_BINARY 3 /* success using the binary search */ |
|
658 |
#define BTR_CUR_INSERT_TO_IBUF 4 /* performed the intended insert to |
|
659 |
the insert buffer */
|
|
660 |
||
661 |
/* If pessimistic delete fails because of lack of file space,
|
|
662 |
there is still a good change of success a little later: try this many times,
|
|
663 |
and sleep this many microseconds in between */
|
|
664 |
#define BTR_CUR_RETRY_DELETE_N_TIMES 100
|
|
665 |
#define BTR_CUR_RETRY_SLEEP_TIME 50000
|
|
666 |
||
667 |
/* The reference in a field for which data is stored on a different page.
|
|
668 |
The reference is at the end of the 'locally' stored part of the field.
|
|
669 |
'Locally' means storage in the index record.
|
|
670 |
We store locally a long enough prefix of each column so that we can determine
|
|
671 |
the ordering parts of each index record without looking into the externally
|
|
672 |
stored part. */
|
|
673 |
||
674 |
/*--------------------------------------*/
|
|
675 |
#define BTR_EXTERN_SPACE_ID 0 /* space id where stored */ |
|
676 |
#define BTR_EXTERN_PAGE_NO 4 /* page no where stored */ |
|
677 |
#define BTR_EXTERN_OFFSET 8 /* offset of BLOB header |
|
678 |
on that page */
|
|
679 |
#define BTR_EXTERN_LEN 12 /* 8 bytes containing the |
|
680 |
length of the externally
|
|
681 |
stored part of the BLOB.
|
|
682 |
The 2 highest bits are
|
|
683 |
reserved to the flags below. */
|
|
684 |
/*--------------------------------------*/
|
|
685 |
#define BTR_EXTERN_FIELD_REF_SIZE 20
|
|
686 |
||
687 |
/* The highest bit of BTR_EXTERN_LEN (i.e., the highest bit of the byte
|
|
688 |
at lowest address) is set to 1 if this field does not 'own' the externally
|
|
689 |
stored field; only the owner field is allowed to free the field in purge!
|
|
690 |
If the 2nd highest bit is 1 then it means that the externally stored field
|
|
691 |
was inherited from an earlier version of the row. In rollback we are not
|
|
692 |
allowed to free an inherited external field. */
|
|
693 |
||
694 |
#define BTR_EXTERN_OWNER_FLAG 128
|
|
695 |
#define BTR_EXTERN_INHERITED_FLAG 64
|
|
696 |
||
697 |
extern ulint btr_cur_n_non_sea; |
|
698 |
extern ulint btr_cur_n_sea; |
|
699 |
extern ulint btr_cur_n_non_sea_old; |
|
700 |
extern ulint btr_cur_n_sea_old; |
|
701 |
||
702 |
#ifndef UNIV_NONINL
|
|
703 |
#include "btr0cur.ic" |
|
704 |
#endif
|
|
705 |
||
706 |
#endif
|