| 1 | /***************************************************************************** |
| 2 | |
| 3 | Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. |
| 4 | Copyright (c) 2017, 2018, MariaDB Corporation. |
| 5 | |
| 6 | This program is free software; you can redistribute it and/or modify it under |
| 7 | the terms of the GNU General Public License as published by the Free Software |
| 8 | Foundation; version 2 of the License. |
| 9 | |
| 10 | This program is distributed in the hope that it will be useful, but WITHOUT |
| 11 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
| 12 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
| 13 | |
| 14 | You should have received a copy of the GNU General Public License along with |
| 15 | this program; if not, write to the Free Software Foundation, Inc., |
| 16 | 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA |
| 17 | |
| 18 | *****************************************************************************/ |
| 19 | |
| 20 | /**************************************************//** |
| 21 | @file include/btr0cur.h |
| 22 | The index tree cursor |
| 23 | |
| 24 | Created 10/16/1994 Heikki Tuuri |
| 25 | *******************************************************/ |
| 26 | |
| 27 | #ifndef btr0cur_h |
| 28 | #define btr0cur_h |
| 29 | |
| 30 | #include "univ.i" |
| 31 | #include "my_base.h" |
| 32 | #include "dict0dict.h" |
| 33 | #include "page0cur.h" |
| 34 | #include "btr0types.h" |
| 35 | #include "gis0type.h" |
| 36 | |
| 37 | /** Mode flags for btr_cur operations; these can be ORed */ |
| 38 | enum { |
| 39 | /** do no undo logging */ |
| 40 | BTR_NO_UNDO_LOG_FLAG = 1, |
| 41 | /** do no record lock checking */ |
| 42 | BTR_NO_LOCKING_FLAG = 2, |
| 43 | /** sys fields will be found in the update vector or inserted |
| 44 | entry */ |
| 45 | BTR_KEEP_SYS_FLAG = 4, |
| 46 | |
| 47 | /** no rollback */ |
| 48 | BTR_NO_ROLLBACK = BTR_NO_UNDO_LOG_FLAG |
| 49 | | BTR_NO_LOCKING_FLAG | BTR_KEEP_SYS_FLAG, |
| 50 | |
| 51 | /** btr_cur_pessimistic_update() must keep cursor position |
| 52 | when moving columns to big_rec */ |
| 53 | BTR_KEEP_POS_FLAG = 8, |
| 54 | /** the caller is creating the index or wants to bypass the |
| 55 | index->info.online creation log */ |
| 56 | BTR_CREATE_FLAG = 16, |
| 57 | /** the caller of btr_cur_optimistic_update() or |
| 58 | btr_cur_update_in_place() will take care of |
| 59 | updating IBUF_BITMAP_FREE */ |
| 60 | BTR_KEEP_IBUF_BITMAP = 32 |
| 61 | }; |
| 62 | |
| 63 | /* btr_cur_latch_leaves() returns latched blocks and savepoints. */ |
| 64 | struct btr_latch_leaves_t { |
| 65 | /* left block, target block and right block */ |
| 66 | buf_block_t* blocks[3]; |
| 67 | ulint savepoints[3]; |
| 68 | }; |
| 69 | |
| 70 | #include "que0types.h" |
| 71 | #include "row0types.h" |
| 72 | #include "ha0ha.h" |
| 73 | |
| 74 | #ifdef UNIV_DEBUG |
| 75 | /*********************************************************//** |
| 76 | Returns the page cursor component of a tree cursor. |
| 77 | @return pointer to page cursor component */ |
| 78 | UNIV_INLINE |
| 79 | page_cur_t* |
| 80 | btr_cur_get_page_cur( |
| 81 | /*=================*/ |
| 82 | const btr_cur_t* cursor);/*!< in: tree cursor */ |
| 83 | /*********************************************************//** |
| 84 | Returns the buffer block on which the tree cursor is positioned. |
| 85 | @return pointer to buffer block */ |
| 86 | UNIV_INLINE |
| 87 | buf_block_t* |
| 88 | btr_cur_get_block( |
| 89 | /*==============*/ |
| 90 | const btr_cur_t* cursor);/*!< in: tree cursor */ |
| 91 | /*********************************************************//** |
| 92 | Returns the record pointer of a tree cursor. |
| 93 | @return pointer to record */ |
| 94 | UNIV_INLINE |
| 95 | rec_t* |
| 96 | btr_cur_get_rec( |
| 97 | /*============*/ |
| 98 | const btr_cur_t* cursor);/*!< in: tree cursor */ |
| 99 | #else /* UNIV_DEBUG */ |
| 100 | # define btr_cur_get_page_cur(cursor) (&(cursor)->page_cur) |
| 101 | # define btr_cur_get_block(cursor) ((cursor)->page_cur.block) |
| 102 | # define btr_cur_get_rec(cursor) ((cursor)->page_cur.rec) |
| 103 | #endif /* UNIV_DEBUG */ |
| 104 | /*********************************************************//** |
| 105 | Returns the compressed page on which the tree cursor is positioned. |
| 106 | @return pointer to compressed page, or NULL if the page is not compressed */ |
| 107 | UNIV_INLINE |
| 108 | page_zip_des_t* |
| 109 | btr_cur_get_page_zip( |
| 110 | /*=================*/ |
| 111 | btr_cur_t* cursor);/*!< in: tree cursor */ |
| 112 | /*********************************************************//** |
| 113 | Returns the page of a tree cursor. |
| 114 | @return pointer to page */ |
| 115 | UNIV_INLINE |
| 116 | page_t* |
| 117 | btr_cur_get_page( |
| 118 | /*=============*/ |
| 119 | btr_cur_t* cursor);/*!< in: tree cursor */ |
| 120 | /*********************************************************//** |
| 121 | Returns the index of a cursor. |
| 122 | @param cursor b-tree cursor |
| 123 | @return index */ |
| 124 | #define btr_cur_get_index(cursor) ((cursor)->index) |
| 125 | /*********************************************************//** |
| 126 | Positions a tree cursor at a given record. */ |
| 127 | UNIV_INLINE |
| 128 | void |
| 129 | btr_cur_position( |
| 130 | /*=============*/ |
| 131 | dict_index_t* index, /*!< in: index */ |
| 132 | rec_t* rec, /*!< in: record in tree */ |
| 133 | buf_block_t* block, /*!< in: buffer block of rec */ |
| 134 | btr_cur_t* cursor);/*!< in: cursor */ |
| 135 | |
| 136 | /** Load the instant ALTER TABLE metadata from the clustered index |
| 137 | when loading a table definition. |
| 138 | @param[in,out] table table definition from the data dictionary |
| 139 | @return error code |
| 140 | @retval DB_SUCCESS if no error occurred */ |
| 141 | dberr_t |
| 142 | btr_cur_instant_init(dict_table_t* table) |
| 143 | ATTRIBUTE_COLD __attribute__((nonnull, warn_unused_result)); |
| 144 | |
| 145 | /** Initialize the n_core_null_bytes on first access to a clustered |
| 146 | index root page. |
| 147 | @param[in] index clustered index that is on its first access |
| 148 | @param[in] page clustered index root page |
| 149 | @return whether the page is corrupted */ |
| 150 | bool |
| 151 | btr_cur_instant_root_init(dict_index_t* index, const page_t* page) |
| 152 | ATTRIBUTE_COLD __attribute__((nonnull, warn_unused_result)); |
| 153 | |
| 154 | /** Optimistically latches the leaf page or pages requested. |
| 155 | @param[in] block guessed buffer block |
| 156 | @param[in] modify_clock modify clock value |
| 157 | @param[in,out] latch_mode BTR_SEARCH_LEAF, ... |
| 158 | @param[in,out] cursor cursor |
| 159 | @param[in] file file name |
| 160 | @param[in] line line where called |
| 161 | @param[in] mtr mini-transaction |
| 162 | @return true if success */ |
| 163 | bool |
| 164 | btr_cur_optimistic_latch_leaves( |
| 165 | buf_block_t* block, |
| 166 | ib_uint64_t modify_clock, |
| 167 | ulint* latch_mode, |
| 168 | btr_cur_t* cursor, |
| 169 | const char* file, |
| 170 | unsigned line, |
| 171 | mtr_t* mtr); |
| 172 | |
| 173 | /********************************************************************//** |
| 174 | Searches an index tree and positions a tree cursor on a given level. |
| 175 | NOTE: n_fields_cmp in tuple must be set so that it cannot be compared |
| 176 | to node pointer page number fields on the upper levels of the tree! |
| 177 | Note that if mode is PAGE_CUR_LE, which is used in inserts, then |
| 178 | cursor->up_match and cursor->low_match both will have sensible values. |
| 179 | If mode is PAGE_CUR_GE, then up_match will a have a sensible value. */ |
| 180 | dberr_t |
| 181 | btr_cur_search_to_nth_level_func( |
| 182 | dict_index_t* index, /*!< in: index */ |
| 183 | ulint level, /*!< in: the tree level of search */ |
| 184 | const dtuple_t* tuple, /*!< in: data tuple; NOTE: n_fields_cmp in |
| 185 | tuple must be set so that it cannot get |
| 186 | compared to the node ptr page number field! */ |
| 187 | page_cur_mode_t mode, /*!< in: PAGE_CUR_L, ...; |
| 188 | NOTE that if the search is made using a unique |
| 189 | prefix of a record, mode should be PAGE_CUR_LE, |
| 190 | not PAGE_CUR_GE, as the latter may end up on |
| 191 | the previous page of the record! Inserts |
| 192 | should always be made using PAGE_CUR_LE to |
| 193 | search the position! */ |
| 194 | ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ..., ORed with |
| 195 | at most one of BTR_INSERT, BTR_DELETE_MARK, |
| 196 | BTR_DELETE, or BTR_ESTIMATE; |
| 197 | cursor->left_block is used to store a pointer |
| 198 | to the left neighbor page, in the cases |
| 199 | BTR_SEARCH_PREV and BTR_MODIFY_PREV; |
| 200 | NOTE that if ahi_latch, we might not have a |
| 201 | cursor page latch, we assume that ahi_latch |
| 202 | protects the record! */ |
| 203 | btr_cur_t* cursor, /*!< in/out: tree cursor; the cursor page is |
| 204 | s- or x-latched, but see also above! */ |
| 205 | #ifdef BTR_CUR_HASH_ADAPT |
| 206 | rw_lock_t* ahi_latch, |
| 207 | /*!< in: currently held btr_search_latch |
| 208 | (in RW_S_LATCH mode), or NULL */ |
| 209 | #endif /* BTR_CUR_HASH_ADAPT */ |
| 210 | const char* file, /*!< in: file name */ |
| 211 | unsigned line, /*!< in: line where called */ |
| 212 | mtr_t* mtr, /*!< in/out: mini-transaction */ |
| 213 | ib_uint64_t autoinc = 0); |
| 214 | /*!< in: PAGE_ROOT_AUTO_INC to be written |
| 215 | (0 if none) */ |
| 216 | #ifdef BTR_CUR_HASH_ADAPT |
| 217 | # define btr_cur_search_to_nth_level(i,l,t,m,lm,c,a,fi,li,mtr) \ |
| 218 | btr_cur_search_to_nth_level_func(i,l,t,m,lm,c,a,fi,li,mtr) |
| 219 | #else /* BTR_CUR_HASH_ADAPT */ |
| 220 | # define btr_cur_search_to_nth_level(i,l,t,m,lm,c,a,fi,li,mtr) \ |
| 221 | btr_cur_search_to_nth_level_func(i,l,t,m,lm,c,fi,li,mtr) |
| 222 | #endif /* BTR_CUR_HASH_ADAPT */ |
| 223 | |
| 224 | /*****************************************************************//** |
| 225 | Opens a cursor at either end of an index. |
| 226 | @return DB_SUCCESS or error code */ |
| 227 | dberr_t |
| 228 | btr_cur_open_at_index_side_func( |
| 229 | /*============================*/ |
| 230 | bool from_left, /*!< in: true if open to the low end, |
| 231 | false if to the high end */ |
| 232 | dict_index_t* index, /*!< in: index */ |
| 233 | ulint latch_mode, /*!< in: latch mode */ |
| 234 | btr_cur_t* cursor, /*!< in/out: cursor */ |
| 235 | ulint level, /*!< in: level to search for |
| 236 | (0=leaf) */ |
| 237 | const char* file, /*!< in: file name */ |
| 238 | unsigned line, /*!< in: line where called */ |
| 239 | mtr_t* mtr) /*!< in/out: mini-transaction */ |
| 240 | MY_ATTRIBUTE((nonnull)); |
| 241 | |
| 242 | #define btr_cur_open_at_index_side(f,i,l,c,lv,m) \ |
| 243 | btr_cur_open_at_index_side_func(f,i,l,c,lv,__FILE__,__LINE__,m) |
| 244 | |
| 245 | /**********************************************************************//** |
| 246 | Positions a cursor at a randomly chosen position within a B-tree. |
| 247 | @return true if the index is available and we have put the cursor, false |
| 248 | if the index is unavailable */ |
| 249 | bool |
| 250 | btr_cur_open_at_rnd_pos_func( |
| 251 | /*=========================*/ |
| 252 | dict_index_t* index, /*!< in: index */ |
| 253 | ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */ |
| 254 | btr_cur_t* cursor, /*!< in/out: B-tree cursor */ |
| 255 | const char* file, /*!< in: file name */ |
| 256 | unsigned line, /*!< in: line where called */ |
| 257 | mtr_t* mtr); /*!< in: mtr */ |
| 258 | #define btr_cur_open_at_rnd_pos(i,l,c,m) \ |
| 259 | btr_cur_open_at_rnd_pos_func(i,l,c,__FILE__,__LINE__,m) |
| 260 | /*************************************************************//** |
| 261 | Tries to perform an insert to a page in an index tree, next to cursor. |
| 262 | It is assumed that mtr holds an x-latch on the page. The operation does |
| 263 | not succeed if there is too little space on the page. If there is just |
| 264 | one record on the page, the insert will always succeed; this is to |
| 265 | prevent trying to split a page with just one record. |
| 266 | @return DB_SUCCESS, DB_WAIT_LOCK, DB_FAIL, or error number */ |
| 267 | dberr_t |
| 268 | btr_cur_optimistic_insert( |
| 269 | /*======================*/ |
| 270 | ulint flags, /*!< in: undo logging and locking flags: if not |
| 271 | zero, the parameters index and thr should be |
| 272 | specified */ |
| 273 | btr_cur_t* cursor, /*!< in: cursor on page after which to insert; |
| 274 | cursor stays valid */ |
| 275 | ulint** offsets,/*!< out: offsets on *rec */ |
| 276 | mem_heap_t** heap, /*!< in/out: pointer to memory heap */ |
| 277 | dtuple_t* entry, /*!< in/out: entry to insert */ |
| 278 | rec_t** rec, /*!< out: pointer to inserted record if |
| 279 | succeed */ |
| 280 | big_rec_t** big_rec,/*!< out: big rec vector whose fields have to |
| 281 | be stored externally by the caller */ |
| 282 | ulint n_ext, /*!< in: number of externally stored columns */ |
| 283 | que_thr_t* thr, /*!< in/out: query thread; can be NULL if |
| 284 | !(~flags |
| 285 | & (BTR_NO_LOCKING_FLAG |
| 286 | | BTR_NO_UNDO_LOG_FLAG)) */ |
| 287 | mtr_t* mtr) /*!< in/out: mini-transaction; |
| 288 | if this function returns DB_SUCCESS on |
| 289 | a leaf page of a secondary index in a |
| 290 | compressed tablespace, the caller must |
| 291 | mtr_commit(mtr) before latching |
| 292 | any further pages */ |
| 293 | MY_ATTRIBUTE((nonnull(2,3,4,5,6,7,10), warn_unused_result)); |
| 294 | /*************************************************************//** |
| 295 | Performs an insert on a page of an index tree. It is assumed that mtr |
| 296 | holds an x-latch on the tree and on the cursor page. If the insert is |
| 297 | made on the leaf level, to avoid deadlocks, mtr must also own x-latches |
| 298 | to brothers of page, if those brothers exist. |
| 299 | @return DB_SUCCESS or error number */ |
| 300 | dberr_t |
| 301 | btr_cur_pessimistic_insert( |
| 302 | /*=======================*/ |
| 303 | ulint flags, /*!< in: undo logging and locking flags: if not |
| 304 | zero, the parameter thr should be |
| 305 | specified; if no undo logging is specified, |
| 306 | then the caller must have reserved enough |
| 307 | free extents in the file space so that the |
| 308 | insertion will certainly succeed */ |
| 309 | btr_cur_t* cursor, /*!< in: cursor after which to insert; |
| 310 | cursor stays valid */ |
| 311 | ulint** offsets,/*!< out: offsets on *rec */ |
| 312 | mem_heap_t** heap, /*!< in/out: pointer to memory heap |
| 313 | that can be emptied */ |
| 314 | dtuple_t* entry, /*!< in/out: entry to insert */ |
| 315 | rec_t** rec, /*!< out: pointer to inserted record if |
| 316 | succeed */ |
| 317 | big_rec_t** big_rec,/*!< out: big rec vector whose fields have to |
| 318 | be stored externally by the caller */ |
| 319 | ulint n_ext, /*!< in: number of externally stored columns */ |
| 320 | que_thr_t* thr, /*!< in/out: query thread; can be NULL if |
| 321 | !(~flags |
| 322 | & (BTR_NO_LOCKING_FLAG |
| 323 | | BTR_NO_UNDO_LOG_FLAG)) */ |
| 324 | mtr_t* mtr) /*!< in/out: mini-transaction */ |
| 325 | MY_ATTRIBUTE((nonnull(2,3,4,5,6,7,10), warn_unused_result)); |
| 326 | /*************************************************************//** |
| 327 | See if there is enough place in the page modification log to log |
| 328 | an update-in-place. |
| 329 | |
| 330 | @retval false if out of space; IBUF_BITMAP_FREE will be reset |
| 331 | outside mtr if the page was recompressed |
| 332 | @retval true if enough place; |
| 333 | |
| 334 | IMPORTANT: The caller will have to update IBUF_BITMAP_FREE if this is |
| 335 | a secondary index leaf page. This has to be done either within the |
| 336 | same mini-transaction, or by invoking ibuf_reset_free_bits() before |
| 337 | mtr_commit(mtr). */ |
| 338 | bool |
| 339 | btr_cur_update_alloc_zip_func( |
| 340 | /*==========================*/ |
| 341 | page_zip_des_t* page_zip,/*!< in/out: compressed page */ |
| 342 | page_cur_t* cursor, /*!< in/out: B-tree page cursor */ |
| 343 | dict_index_t* index, /*!< in: the index corresponding to cursor */ |
| 344 | #ifdef UNIV_DEBUG |
| 345 | ulint* offsets,/*!< in/out: offsets of the cursor record */ |
| 346 | #endif /* UNIV_DEBUG */ |
| 347 | ulint length, /*!< in: size needed */ |
| 348 | bool create, /*!< in: true=delete-and-insert, |
| 349 | false=update-in-place */ |
| 350 | mtr_t* mtr) /*!< in/out: mini-transaction */ |
| 351 | MY_ATTRIBUTE((nonnull, warn_unused_result)); |
| 352 | #ifdef UNIV_DEBUG |
| 353 | # define btr_cur_update_alloc_zip(page_zip,cursor,index,offsets,len,cr,mtr) \ |
| 354 | btr_cur_update_alloc_zip_func(page_zip,cursor,index,offsets,len,cr,mtr) |
| 355 | #else /* UNIV_DEBUG */ |
| 356 | # define btr_cur_update_alloc_zip(page_zip,cursor,index,offsets,len,cr,mtr) \ |
| 357 | btr_cur_update_alloc_zip_func(page_zip,cursor,index,len,cr,mtr) |
| 358 | #endif /* UNIV_DEBUG */ |
| 359 | /*************************************************************//** |
| 360 | Updates a record when the update causes no size changes in its fields. |
| 361 | @return locking or undo log related error code, or |
| 362 | @retval DB_SUCCESS on success |
| 363 | @retval DB_ZIP_OVERFLOW if there is not enough space left |
| 364 | on the compressed page (IBUF_BITMAP_FREE was reset outside mtr) */ |
| 365 | dberr_t |
| 366 | btr_cur_update_in_place( |
| 367 | /*====================*/ |
| 368 | ulint flags, /*!< in: undo logging and locking flags */ |
| 369 | btr_cur_t* cursor, /*!< in: cursor on the record to update; |
| 370 | cursor stays valid and positioned on the |
| 371 | same record */ |
| 372 | ulint* offsets,/*!< in/out: offsets on cursor->page_cur.rec */ |
| 373 | const upd_t* update, /*!< in: update vector */ |
| 374 | ulint cmpl_info,/*!< in: compiler info on secondary index |
| 375 | updates */ |
| 376 | que_thr_t* thr, /*!< in: query thread */ |
| 377 | trx_id_t trx_id, /*!< in: transaction id */ |
| 378 | mtr_t* mtr) /*!< in/out: mini-transaction; if this |
| 379 | is a secondary index, the caller must |
| 380 | mtr_commit(mtr) before latching any |
| 381 | further pages */ |
| 382 | MY_ATTRIBUTE((warn_unused_result, nonnull)); |
| 383 | /***********************************************************//** |
| 384 | Writes a redo log record of updating a record in-place. */ |
| 385 | void |
| 386 | btr_cur_update_in_place_log( |
| 387 | /*========================*/ |
| 388 | ulint flags, /*!< in: flags */ |
| 389 | const rec_t* rec, /*!< in: record */ |
| 390 | dict_index_t* index, /*!< in: index of the record */ |
| 391 | const upd_t* update, /*!< in: update vector */ |
| 392 | trx_id_t trx_id, /*!< in: transaction id */ |
| 393 | roll_ptr_t roll_ptr, /*!< in: roll ptr */ |
| 394 | mtr_t* mtr) /*!< in: mtr */ |
| 395 | MY_ATTRIBUTE((nonnull)); |
| 396 | /*************************************************************//** |
| 397 | Tries to update a record on a page in an index tree. It is assumed that mtr |
| 398 | holds an x-latch on the page. The operation does not succeed if there is too |
| 399 | little space on the page or if the update would result in too empty a page, |
| 400 | so that tree compression is recommended. |
| 401 | @return error code, including |
| 402 | @retval DB_SUCCESS on success |
| 403 | @retval DB_OVERFLOW if the updated record does not fit |
| 404 | @retval DB_UNDERFLOW if the page would become too empty |
| 405 | @retval DB_ZIP_OVERFLOW if there is not enough space left |
| 406 | on the compressed page */ |
| 407 | dberr_t |
| 408 | btr_cur_optimistic_update( |
| 409 | /*======================*/ |
| 410 | ulint flags, /*!< in: undo logging and locking flags */ |
| 411 | btr_cur_t* cursor, /*!< in: cursor on the record to update; |
| 412 | cursor stays valid and positioned on the |
| 413 | same record */ |
| 414 | ulint** offsets,/*!< out: offsets on cursor->page_cur.rec */ |
| 415 | mem_heap_t** heap, /*!< in/out: pointer to NULL or memory heap */ |
| 416 | const upd_t* update, /*!< in: update vector; this must also |
| 417 | contain trx id and roll ptr fields */ |
| 418 | ulint cmpl_info,/*!< in: compiler info on secondary index |
| 419 | updates */ |
| 420 | que_thr_t* thr, /*!< in: query thread */ |
| 421 | trx_id_t trx_id, /*!< in: transaction id */ |
| 422 | mtr_t* mtr) /*!< in/out: mini-transaction; if this |
| 423 | is a secondary index, the caller must |
| 424 | mtr_commit(mtr) before latching any |
| 425 | further pages */ |
| 426 | MY_ATTRIBUTE((warn_unused_result, nonnull)); |
| 427 | /*************************************************************//** |
| 428 | Performs an update of a record on a page of a tree. It is assumed |
| 429 | that mtr holds an x-latch on the tree and on the cursor page. If the |
| 430 | update is made on the leaf level, to avoid deadlocks, mtr must also |
| 431 | own x-latches to brothers of page, if those brothers exist. |
| 432 | @return DB_SUCCESS or error code */ |
| 433 | dberr_t |
| 434 | btr_cur_pessimistic_update( |
| 435 | /*=======================*/ |
| 436 | ulint flags, /*!< in: undo logging, locking, and rollback |
| 437 | flags */ |
| 438 | btr_cur_t* cursor, /*!< in/out: cursor on the record to update; |
| 439 | cursor may become invalid if *big_rec == NULL |
| 440 | || !(flags & BTR_KEEP_POS_FLAG) */ |
| 441 | ulint** offsets,/*!< out: offsets on cursor->page_cur.rec */ |
| 442 | mem_heap_t** offsets_heap, |
| 443 | /*!< in/out: pointer to memory heap |
| 444 | that can be emptied */ |
| 445 | mem_heap_t* entry_heap, |
| 446 | /*!< in/out: memory heap for allocating |
| 447 | big_rec and the index tuple */ |
| 448 | big_rec_t** big_rec,/*!< out: big rec vector whose fields have to |
| 449 | be stored externally by the caller */ |
| 450 | upd_t* update, /*!< in/out: update vector; this is allowed to |
| 451 | also contain trx id and roll ptr fields. |
| 452 | Non-updated columns that are moved offpage will |
| 453 | be appended to this. */ |
| 454 | ulint cmpl_info,/*!< in: compiler info on secondary index |
| 455 | updates */ |
| 456 | que_thr_t* thr, /*!< in: query thread */ |
| 457 | trx_id_t trx_id, /*!< in: transaction id */ |
| 458 | mtr_t* mtr) /*!< in/out: mini-transaction; must be committed |
| 459 | before latching any further pages */ |
| 460 | MY_ATTRIBUTE((warn_unused_result, nonnull)); |
| 461 | /***********************************************************//** |
| 462 | Marks a clustered index record deleted. Writes an undo log record to |
| 463 | undo log on this delete marking. Writes in the trx id field the id |
| 464 | of the deleting transaction, and in the roll ptr field pointer to the |
| 465 | undo log record created. |
| 466 | @return DB_SUCCESS, DB_LOCK_WAIT, or error number */ |
| 467 | dberr_t |
| 468 | btr_cur_del_mark_set_clust_rec( |
| 469 | /*===========================*/ |
| 470 | buf_block_t* block, /*!< in/out: buffer block of the record */ |
| 471 | rec_t* rec, /*!< in/out: record */ |
| 472 | dict_index_t* index, /*!< in: clustered index of the record */ |
| 473 | const ulint* offsets,/*!< in: rec_get_offsets(rec) */ |
| 474 | que_thr_t* thr, /*!< in: query thread */ |
| 475 | const dtuple_t* entry, /*!< in: dtuple for the deleting record */ |
| 476 | mtr_t* mtr) /*!< in/out: mini-transaction */ |
| 477 | MY_ATTRIBUTE((nonnull, warn_unused_result)); |
| 478 | /***********************************************************//** |
| 479 | Sets a secondary index record delete mark to TRUE or FALSE. |
| 480 | @return DB_SUCCESS, DB_LOCK_WAIT, or error number */ |
| 481 | dberr_t |
| 482 | btr_cur_del_mark_set_sec_rec( |
| 483 | /*=========================*/ |
| 484 | ulint flags, /*!< in: locking flag */ |
| 485 | btr_cur_t* cursor, /*!< in: cursor */ |
| 486 | ibool val, /*!< in: value to set */ |
| 487 | que_thr_t* thr, /*!< in: query thread */ |
| 488 | mtr_t* mtr) /*!< in/out: mini-transaction */ |
| 489 | MY_ATTRIBUTE((nonnull, warn_unused_result)); |
| 490 | /*************************************************************//** |
| 491 | Tries to compress a page of the tree if it seems useful. It is assumed |
| 492 | that mtr holds an x-latch on the tree and on the cursor page. To avoid |
| 493 | deadlocks, mtr must also own x-latches to brothers of page, if those |
| 494 | brothers exist. NOTE: it is assumed that the caller has reserved enough |
| 495 | free extents so that the compression will always succeed if done! |
| 496 | @return TRUE if compression occurred */ |
| 497 | ibool |
| 498 | btr_cur_compress_if_useful( |
| 499 | /*=======================*/ |
| 500 | btr_cur_t* cursor, /*!< in/out: cursor on the page to compress; |
| 501 | cursor does not stay valid if compression |
| 502 | occurs */ |
| 503 | ibool adjust, /*!< in: TRUE if should adjust the |
| 504 | cursor position even if compression occurs */ |
| 505 | mtr_t* mtr) /*!< in/out: mini-transaction */ |
| 506 | MY_ATTRIBUTE((nonnull)); |
| 507 | /*******************************************************//** |
| 508 | Removes the record on which the tree cursor is positioned. It is assumed |
| 509 | that the mtr has an x-latch on the page where the cursor is positioned, |
| 510 | but no latch on the whole tree. |
| 511 | @return TRUE if success, i.e., the page did not become too empty */ |
| 512 | ibool |
| 513 | btr_cur_optimistic_delete_func( |
| 514 | /*===========================*/ |
| 515 | btr_cur_t* cursor, /*!< in: cursor on the record to delete; |
| 516 | cursor stays valid: if deletion succeeds, |
| 517 | on function exit it points to the successor |
| 518 | of the deleted record */ |
| 519 | # ifdef UNIV_DEBUG |
| 520 | ulint flags, /*!< in: BTR_CREATE_FLAG or 0 */ |
| 521 | # endif /* UNIV_DEBUG */ |
| 522 | mtr_t* mtr) /*!< in: mtr; if this function returns |
| 523 | TRUE on a leaf page of a secondary |
| 524 | index, the mtr must be committed |
| 525 | before latching any further pages */ |
| 526 | MY_ATTRIBUTE((nonnull, warn_unused_result)); |
| 527 | # ifdef UNIV_DEBUG |
| 528 | # define btr_cur_optimistic_delete(cursor, flags, mtr) \ |
| 529 | btr_cur_optimistic_delete_func(cursor, flags, mtr) |
| 530 | # else /* UNIV_DEBUG */ |
| 531 | # define btr_cur_optimistic_delete(cursor, flags, mtr) \ |
| 532 | btr_cur_optimistic_delete_func(cursor, mtr) |
| 533 | # endif /* UNIV_DEBUG */ |
| 534 | /*************************************************************//** |
| 535 | Removes the record on which the tree cursor is positioned. Tries |
| 536 | to compress the page if its fillfactor drops below a threshold |
| 537 | or if it is the only page on the level. It is assumed that mtr holds |
| 538 | an x-latch on the tree and on the cursor page. To avoid deadlocks, |
| 539 | mtr must also own x-latches to brothers of page, if those brothers |
| 540 | exist. |
| 541 | @return TRUE if compression occurred */ |
| 542 | ibool |
| 543 | btr_cur_pessimistic_delete( |
| 544 | /*=======================*/ |
| 545 | dberr_t* err, /*!< out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE; |
| 546 | the latter may occur because we may have |
| 547 | to update node pointers on upper levels, |
| 548 | and in the case of variable length keys |
| 549 | these may actually grow in size */ |
| 550 | ibool has_reserved_extents, /*!< in: TRUE if the |
| 551 | caller has already reserved enough free |
| 552 | extents so that he knows that the operation |
| 553 | will succeed */ |
| 554 | btr_cur_t* cursor, /*!< in: cursor on the record to delete; |
| 555 | if compression does not occur, the cursor |
| 556 | stays valid: it points to successor of |
| 557 | deleted record on function exit */ |
| 558 | ulint flags, /*!< in: BTR_CREATE_FLAG or 0 */ |
| 559 | bool rollback,/*!< in: performing rollback? */ |
| 560 | mtr_t* mtr) /*!< in: mtr */ |
| 561 | MY_ATTRIBUTE((nonnull)); |
| 562 | /***********************************************************//** |
| 563 | Parses a redo log record of updating a record in-place. |
| 564 | @return end of log record or NULL */ |
| 565 | byte* |
| 566 | btr_cur_parse_update_in_place( |
| 567 | /*==========================*/ |
| 568 | byte* ptr, /*!< in: buffer */ |
| 569 | byte* end_ptr,/*!< in: buffer end */ |
| 570 | page_t* page, /*!< in/out: page or NULL */ |
| 571 | page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */ |
| 572 | dict_index_t* index); /*!< in: index corresponding to page */ |
| 573 | /****************************************************************//** |
| 574 | Parses the redo log record for delete marking or unmarking of a clustered |
| 575 | index record. |
| 576 | @return end of log record or NULL */ |
| 577 | byte* |
| 578 | btr_cur_parse_del_mark_set_clust_rec( |
| 579 | /*=================================*/ |
| 580 | byte* ptr, /*!< in: buffer */ |
| 581 | byte* end_ptr,/*!< in: buffer end */ |
| 582 | page_t* page, /*!< in/out: page or NULL */ |
| 583 | page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */ |
| 584 | dict_index_t* index); /*!< in: index corresponding to page */ |
| 585 | /****************************************************************//** |
| 586 | Parses the redo log record for delete marking or unmarking of a secondary |
| 587 | index record. |
| 588 | @return end of log record or NULL */ |
| 589 | byte* |
| 590 | btr_cur_parse_del_mark_set_sec_rec( |
| 591 | /*===============================*/ |
| 592 | byte* ptr, /*!< in: buffer */ |
| 593 | byte* end_ptr,/*!< in: buffer end */ |
| 594 | page_t* page, /*!< in/out: page or NULL */ |
| 595 | page_zip_des_t* page_zip);/*!< in/out: compressed page, or NULL */ |
| 596 | |
| 597 | /** Estimates the number of rows in a given index range. |
| 598 | @param[in] index index |
| 599 | @param[in] tuple1 range start, may also be empty tuple |
| 600 | @param[in] mode1 search mode for range start |
| 601 | @param[in] tuple2 range end, may also be empty tuple |
| 602 | @param[in] mode2 search mode for range end |
| 603 | @return estimated number of rows */ |
| 604 | ha_rows |
| 605 | btr_estimate_n_rows_in_range( |
| 606 | dict_index_t* index, |
| 607 | const dtuple_t* tuple1, |
| 608 | page_cur_mode_t mode1, |
| 609 | const dtuple_t* tuple2, |
| 610 | page_cur_mode_t mode2); |
| 611 | |
| 612 | /*******************************************************************//** |
| 613 | Estimates the number of different key values in a given index, for |
| 614 | each n-column prefix of the index where 1 <= n <= dict_index_get_n_unique(index). |
| 615 | The estimates are stored in the array index->stat_n_diff_key_vals[] (indexed |
| 616 | 0..n_uniq-1) and the number of pages that were sampled is saved in |
| 617 | index->stat_n_sample_sizes[]. |
| 618 | If innodb_stats_method is nulls_ignored, we also record the number of |
| 619 | non-null values for each prefix and stored the estimates in |
| 620 | array index->stat_n_non_null_key_vals. |
| 621 | @return true if the index is available and we get the estimated numbers, |
| 622 | false if the index is unavailable. */ |
| 623 | bool |
| 624 | btr_estimate_number_of_different_key_vals( |
| 625 | /*======================================*/ |
| 626 | dict_index_t* index); /*!< in: index */ |
| 627 | |
| 628 | /** Gets the externally stored size of a record, in units of a database page. |
| 629 | @param[in] rec record |
| 630 | @param[in] offsets array returned by rec_get_offsets() |
| 631 | @return externally stored part, in units of a database page */ |
| 632 | ulint |
| 633 | btr_rec_get_externally_stored_len( |
| 634 | const rec_t* rec, |
| 635 | const ulint* offsets); |
| 636 | |
| 637 | /*******************************************************************//** |
| 638 | Marks non-updated off-page fields as disowned by this record. The ownership |
| 639 | must be transferred to the updated record which is inserted elsewhere in the |
| 640 | index tree. In purge only the owner of externally stored field is allowed |
| 641 | to free the field. */ |
| 642 | void |
| 643 | btr_cur_disown_inherited_fields( |
| 644 | /*============================*/ |
| 645 | page_zip_des_t* page_zip,/*!< in/out: compressed page whose uncompressed |
| 646 | part will be updated, or NULL */ |
| 647 | rec_t* rec, /*!< in/out: record in a clustered index */ |
| 648 | dict_index_t* index, /*!< in: index of the page */ |
| 649 | const ulint* offsets,/*!< in: array returned by rec_get_offsets() */ |
| 650 | const upd_t* update, /*!< in: update vector */ |
| 651 | mtr_t* mtr) /*!< in/out: mini-transaction */ |
| 652 | MY_ATTRIBUTE((nonnull(2,3,4,5,6))); |
| 653 | |
| 654 | /** Operation code for btr_store_big_rec_extern_fields(). */ |
| 655 | enum blob_op { |
| 656 | /** Store off-page columns for a freshly inserted record */ |
| 657 | BTR_STORE_INSERT = 0, |
| 658 | /** Store off-page columns for an insert by update */ |
| 659 | BTR_STORE_INSERT_UPDATE, |
| 660 | /** Store off-page columns for an update */ |
| 661 | BTR_STORE_UPDATE, |
| 662 | /** Store off-page columns for a freshly inserted record by bulk */ |
| 663 | BTR_STORE_INSERT_BULK |
| 664 | }; |
| 665 | |
| 666 | /*******************************************************************//** |
| 667 | Determine if an operation on off-page columns is an update. |
| 668 | @return TRUE if op != BTR_STORE_INSERT */ |
| 669 | UNIV_INLINE |
| 670 | ibool |
| 671 | btr_blob_op_is_update( |
| 672 | /*==================*/ |
| 673 | enum blob_op op) /*!< in: operation */ |
| 674 | MY_ATTRIBUTE((warn_unused_result)); |
| 675 | |
| 676 | /*******************************************************************//** |
| 677 | Stores the fields in big_rec_vec to the tablespace and puts pointers to |
| 678 | them in rec. The extern flags in rec will have to be set beforehand. |
| 679 | The fields are stored on pages allocated from leaf node |
| 680 | file segment of the index tree. |
| 681 | @return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */ |
| 682 | dberr_t |
| 683 | btr_store_big_rec_extern_fields( |
| 684 | /*============================*/ |
| 685 | btr_pcur_t* pcur, /*!< in/out: a persistent cursor. if |
| 686 | btr_mtr is restarted, then this can |
| 687 | be repositioned. */ |
| 688 | ulint* offsets, /*!< in/out: rec_get_offsets() on |
| 689 | pcur. the "external storage" flags |
| 690 | in offsets will correctly correspond |
| 691 | to rec when this function returns */ |
| 692 | const big_rec_t*big_rec_vec, /*!< in: vector containing fields |
| 693 | to be stored externally */ |
| 694 | mtr_t* btr_mtr, /*!< in/out: mtr containing the |
| 695 | latches to the clustered index. can be |
| 696 | committed and restarted. */ |
| 697 | enum blob_op op) /*! in: operation code */ |
| 698 | MY_ATTRIBUTE((warn_unused_result)); |
| 699 | |
| 700 | /*******************************************************************//** |
| 701 | Frees the space in an externally stored field to the file space |
| 702 | management if the field in data is owned the externally stored field, |
| 703 | in a rollback we may have the additional condition that the field must |
| 704 | not be inherited. */ |
| 705 | void |
| 706 | btr_free_externally_stored_field( |
| 707 | /*=============================*/ |
| 708 | dict_index_t* index, /*!< in: index of the data, the index |
| 709 | tree MUST be X-latched; if the tree |
| 710 | height is 1, then also the root page |
| 711 | must be X-latched! (this is relevant |
| 712 | in the case this function is called |
| 713 | from purge where 'data' is located on |
| 714 | an undo log page, not an index |
| 715 | page) */ |
| 716 | byte* field_ref, /*!< in/out: field reference */ |
| 717 | const rec_t* rec, /*!< in: record containing field_ref, for |
| 718 | page_zip_write_blob_ptr(), or NULL */ |
| 719 | const ulint* offsets, /*!< in: rec_get_offsets(rec, index), |
| 720 | or NULL */ |
| 721 | page_zip_des_t* page_zip, /*!< in: compressed page corresponding |
| 722 | to rec, or NULL if rec == NULL */ |
| 723 | ulint i, /*!< in: field number of field_ref; |
| 724 | ignored if rec == NULL */ |
| 725 | bool rollback, /*!< in: performing rollback? */ |
| 726 | mtr_t* local_mtr); /*!< in: mtr containing the latch */ |
| 727 | /** Copies the prefix of an externally stored field of a record. |
| 728 | The clustered index record must be protected by a lock or a page latch. |
| 729 | @param[out] buf the field, or a prefix of it |
| 730 | @param[in] len length of buf, in bytes |
| 731 | @param[in] page_size BLOB page size |
| 732 | @param[in] data 'internally' stored part of the field |
| 733 | containing also the reference to the external part; must be protected by |
| 734 | a lock or a page latch |
| 735 | @param[in] local_len length of data, in bytes |
| 736 | @return the length of the copied field, or 0 if the column was being |
| 737 | or has been deleted */ |
| 738 | ulint |
| 739 | btr_copy_externally_stored_field_prefix( |
| 740 | byte* buf, |
| 741 | ulint len, |
| 742 | const page_size_t& page_size, |
| 743 | const byte* data, |
| 744 | ulint local_len); |
| 745 | |
| 746 | /** Copies an externally stored field of a record to mem heap. |
| 747 | The clustered index record must be protected by a lock or a page latch. |
| 748 | @param[out] len length of the whole field |
| 749 | @param[in] data 'internally' stored part of the field |
| 750 | containing also the reference to the external part; must be protected by |
| 751 | a lock or a page latch |
| 752 | @param[in] page_size BLOB page size |
| 753 | @param[in] local_len length of data |
| 754 | @param[in,out] heap mem heap |
| 755 | @return the whole field copied to heap */ |
| 756 | byte* |
| 757 | btr_copy_externally_stored_field( |
| 758 | ulint* len, |
| 759 | const byte* data, |
| 760 | const page_size_t& page_size, |
| 761 | ulint local_len, |
| 762 | mem_heap_t* heap); |
| 763 | |
| 764 | /** Copies an externally stored field of a record to mem heap. |
| 765 | @param[in] rec record in a clustered index; must be |
| 766 | protected by a lock or a page latch |
| 767 | @param[in] offset array returned by rec_get_offsets() |
| 768 | @param[in] page_size BLOB page size |
| 769 | @param[in] no field number |
| 770 | @param[out] len length of the field |
| 771 | @param[in,out] heap mem heap |
| 772 | @return the field copied to heap, or NULL if the field is incomplete */ |
| 773 | byte* |
| 774 | btr_rec_copy_externally_stored_field( |
| 775 | const rec_t* rec, |
| 776 | const ulint* offsets, |
| 777 | const page_size_t& page_size, |
| 778 | ulint no, |
| 779 | ulint* len, |
| 780 | mem_heap_t* heap); |
| 781 | |
| 782 | /*******************************************************************//** |
| 783 | Flags the data tuple fields that are marked as extern storage in the |
| 784 | update vector. We use this function to remember which fields we must |
| 785 | mark as extern storage in a record inserted for an update. |
| 786 | @return number of flagged external columns */ |
| 787 | ulint |
| 788 | btr_push_update_extern_fields( |
| 789 | /*==========================*/ |
| 790 | dtuple_t* tuple, /*!< in/out: data tuple */ |
| 791 | const upd_t* update, /*!< in: update vector */ |
| 792 | mem_heap_t* heap) /*!< in: memory heap */ |
| 793 | MY_ATTRIBUTE((nonnull)); |
| 794 | /***********************************************************//** |
| 795 | Sets a secondary index record's delete mark to the given value. This |
| 796 | function is only used by the insert buffer merge mechanism. */ |
| 797 | void |
| 798 | btr_cur_set_deleted_flag_for_ibuf( |
| 799 | /*==============================*/ |
| 800 | rec_t* rec, /*!< in/out: record */ |
| 801 | page_zip_des_t* page_zip, /*!< in/out: compressed page |
| 802 | corresponding to rec, or NULL |
| 803 | when the tablespace is uncompressed */ |
| 804 | ibool val, /*!< in: value to set */ |
| 805 | mtr_t* mtr); /*!< in/out: mini-transaction */ |
| 806 | |
| 807 | /******************************************************//** |
| 808 | The following function is used to set the deleted bit of a record. */ |
| 809 | UNIV_INLINE |
| 810 | void |
| 811 | btr_rec_set_deleted_flag( |
| 812 | /*=====================*/ |
| 813 | rec_t* rec, /*!< in/out: physical record */ |
| 814 | page_zip_des_t* page_zip,/*!< in/out: compressed page (or NULL) */ |
| 815 | ulint flag); /*!< in: nonzero if delete marked */ |
| 816 | |
| 817 | /** Latches the leaf page or pages requested. |
| 818 | @param[in] block leaf page where the search converged |
| 819 | @param[in] page_id page id of the leaf |
| 820 | @param[in] latch_mode BTR_SEARCH_LEAF, ... |
| 821 | @param[in] cursor cursor |
| 822 | @param[in] mtr mini-transaction |
| 823 | @return blocks and savepoints which actually latched. */ |
| 824 | btr_latch_leaves_t |
| 825 | btr_cur_latch_leaves( |
| 826 | buf_block_t* block, |
| 827 | const page_id_t& page_id, |
| 828 | const page_size_t& page_size, |
| 829 | ulint latch_mode, |
| 830 | btr_cur_t* cursor, |
| 831 | mtr_t* mtr); |
| 832 | |
| 833 | /*######################################################################*/ |
| 834 | |
| 835 | /** In the pessimistic delete, if the page data size drops below this |
| 836 | limit, merging it to a neighbor is tried */ |
| 837 | #define BTR_CUR_PAGE_COMPRESS_LIMIT(index) \ |
| 838 | ((srv_page_size * (ulint)((index)->merge_threshold)) / 100) |
| 839 | |
| 840 | /** A slot in the path array. We store here info on a search path down the |
| 841 | tree. Each slot contains data on a single level of the tree. */ |
| 842 | struct btr_path_t { |
| 843 | /* Assume a page like: |
| 844 | records: (inf, a, b, c, d, sup) |
| 845 | index of the record: 0, 1, 2, 3, 4, 5 |
| 846 | */ |
| 847 | |
| 848 | /** Index of the record where the page cursor stopped on this level |
| 849 | (index in alphabetical order). Value ULINT_UNDEFINED denotes array |
| 850 | end. In the above example, if the search stopped on record 'c', then |
| 851 | nth_rec will be 3. */ |
| 852 | ulint nth_rec; |
| 853 | |
| 854 | /** Number of the records on the page, not counting inf and sup. |
| 855 | In the above example n_recs will be 4. */ |
| 856 | ulint n_recs; |
| 857 | |
| 858 | /** Number of the page containing the record. */ |
| 859 | ulint page_no; |
| 860 | |
| 861 | /** Level of the page. If later we fetch the page under page_no |
| 862 | and it is no different level then we know that the tree has been |
| 863 | reorganized. */ |
| 864 | ulint page_level; |
| 865 | }; |
| 866 | |
| 867 | #define BTR_PATH_ARRAY_N_SLOTS 250 /*!< size of path array (in slots) */ |
| 868 | |
| 869 | /** Values for the flag documenting the used search method */ |
| 870 | enum btr_cur_method { |
| 871 | BTR_CUR_HASH = 1, /*!< successful shortcut using |
| 872 | the hash index */ |
| 873 | BTR_CUR_HASH_FAIL, /*!< failure using hash, success using |
| 874 | binary search: the misleading hash |
| 875 | reference is stored in the field |
| 876 | hash_node, and might be necessary to |
| 877 | update */ |
| 878 | BTR_CUR_BINARY, /*!< success using the binary search */ |
| 879 | BTR_CUR_INSERT_TO_IBUF, /*!< performed the intended insert to |
| 880 | the insert buffer */ |
| 881 | BTR_CUR_DEL_MARK_IBUF, /*!< performed the intended delete |
| 882 | mark in the insert/delete buffer */ |
| 883 | BTR_CUR_DELETE_IBUF, /*!< performed the intended delete in |
| 884 | the insert/delete buffer */ |
| 885 | BTR_CUR_DELETE_REF /*!< row_purge_poss_sec() failed */ |
| 886 | }; |
| 887 | |
| 888 | /** The tree cursor: the definition appears here only for the compiler |
| 889 | to know struct size! */ |
| 890 | struct btr_cur_t { |
| 891 | dict_index_t* index; /*!< index where positioned */ |
| 892 | page_cur_t page_cur; /*!< page cursor */ |
| 893 | purge_node_t* purge_node; /*!< purge node, for BTR_DELETE */ |
| 894 | buf_block_t* left_block; /*!< this field is used to store |
| 895 | a pointer to the left neighbor |
| 896 | page, in the cases |
| 897 | BTR_SEARCH_PREV and |
| 898 | BTR_MODIFY_PREV */ |
| 899 | /*------------------------------*/ |
| 900 | que_thr_t* thr; /*!< this field is only used |
| 901 | when btr_cur_search_to_nth_level |
| 902 | is called for an index entry |
| 903 | insertion: the calling query |
| 904 | thread is passed here to be |
| 905 | used in the insert buffer */ |
| 906 | /*------------------------------*/ |
| 907 | /** The following fields are used in |
| 908 | btr_cur_search_to_nth_level to pass information: */ |
| 909 | /* @{ */ |
| 910 | enum btr_cur_method flag; /*!< Search method used */ |
| 911 | ulint tree_height; /*!< Tree height if the search is done |
| 912 | for a pessimistic insert or update |
| 913 | operation */ |
| 914 | ulint up_match; /*!< If the search mode was PAGE_CUR_LE, |
| 915 | the number of matched fields to the |
| 916 | the first user record to the right of |
| 917 | the cursor record after |
| 918 | btr_cur_search_to_nth_level; |
| 919 | for the mode PAGE_CUR_GE, the matched |
| 920 | fields to the first user record AT THE |
| 921 | CURSOR or to the right of it; |
| 922 | NOTE that the up_match and low_match |
| 923 | values may exceed the correct values |
| 924 | for comparison to the adjacent user |
| 925 | record if that record is on a |
| 926 | different leaf page! (See the note in |
| 927 | row_ins_duplicate_error_in_clust.) */ |
| 928 | ulint up_bytes; /*!< number of matched bytes to the |
| 929 | right at the time cursor positioned; |
| 930 | only used internally in searches: not |
| 931 | defined after the search */ |
| 932 | ulint low_match; /*!< if search mode was PAGE_CUR_LE, |
| 933 | the number of matched fields to the |
| 934 | first user record AT THE CURSOR or |
| 935 | to the left of it after |
| 936 | btr_cur_search_to_nth_level; |
| 937 | NOT defined for PAGE_CUR_GE or any |
| 938 | other search modes; see also the NOTE |
| 939 | in up_match! */ |
| 940 | ulint low_bytes; /*!< number of matched bytes to the |
| 941 | left at the time cursor positioned; |
| 942 | only used internally in searches: not |
| 943 | defined after the search */ |
| 944 | ulint n_fields; /*!< prefix length used in a hash |
| 945 | search if hash_node != NULL */ |
| 946 | ulint n_bytes; /*!< hash prefix bytes if hash_node != |
| 947 | NULL */ |
| 948 | ulint fold; /*!< fold value used in the search if |
| 949 | flag is BTR_CUR_HASH */ |
| 950 | /* @} */ |
| 951 | btr_path_t* path_arr; /*!< in estimating the number of |
| 952 | rows in range, we store in this array |
| 953 | information of the path through |
| 954 | the tree */ |
| 955 | rtr_info_t* rtr_info; /*!< rtree search info */ |
| 956 | btr_cur_t():thr(NULL), rtr_info(NULL) {} |
| 957 | /* default values */ |
| 958 | }; |
| 959 | |
| 960 | /******************************************************//** |
| 961 | The following function is used to set the deleted bit of a record. */ |
| 962 | UNIV_INLINE |
| 963 | void |
| 964 | btr_rec_set_deleted_flag( |
| 965 | /*=====================*/ |
| 966 | rec_t* rec, /*!< in/out: physical record */ |
| 967 | page_zip_des_t* page_zip,/*!< in/out: compressed page (or NULL) */ |
| 968 | ulint flag); /*!< in: nonzero if delete marked */ |
| 969 | |
| 970 | /** If pessimistic delete fails because of lack of file space, there |
| 971 | is still a good change of success a little later. Try this many |
| 972 | times. */ |
| 973 | #define BTR_CUR_RETRY_DELETE_N_TIMES 100 |
| 974 | /** If pessimistic delete fails because of lack of file space, there |
| 975 | is still a good change of success a little later. Sleep this many |
| 976 | microseconds between retries. */ |
| 977 | #define BTR_CUR_RETRY_SLEEP_TIME 50000 |
| 978 | |
| 979 | /** The reference in a field for which data is stored on a different page. |
| 980 | The reference is at the end of the 'locally' stored part of the field. |
| 981 | 'Locally' means storage in the index record. |
| 982 | We store locally a long enough prefix of each column so that we can determine |
| 983 | the ordering parts of each index record without looking into the externally |
| 984 | stored part. */ |
| 985 | /*-------------------------------------- @{ */ |
| 986 | #define BTR_EXTERN_SPACE_ID 0U /*!< space id where stored */ |
| 987 | #define BTR_EXTERN_PAGE_NO 4U /*!< page no where stored */ |
| 988 | #define BTR_EXTERN_OFFSET 8U /*!< offset of BLOB header |
| 989 | on that page */ |
| 990 | #define BTR_EXTERN_LEN 12U /*!< 8 bytes containing the |
| 991 | length of the externally |
| 992 | stored part of the BLOB. |
| 993 | The 2 highest bits are |
| 994 | reserved to the flags below. */ |
| 995 | /*-------------------------------------- @} */ |
| 996 | /* #define BTR_EXTERN_FIELD_REF_SIZE 20 // moved to btr0types.h */ |
| 997 | |
| 998 | /** The most significant bit of BTR_EXTERN_LEN (i.e., the most |
| 999 | significant bit of the byte at smallest address) is set to 1 if this |
| 1000 | field does not 'own' the externally stored field; only the owner field |
| 1001 | is allowed to free the field in purge! */ |
| 1002 | #define BTR_EXTERN_OWNER_FLAG 128U |
| 1003 | /** If the second most significant bit of BTR_EXTERN_LEN (i.e., the |
| 1004 | second most significant bit of the byte at smallest address) is 1 then |
| 1005 | it means that the externally stored field was inherited from an |
| 1006 | earlier version of the row. In rollback we are not allowed to free an |
| 1007 | inherited external field. */ |
| 1008 | #define BTR_EXTERN_INHERITED_FLAG 64U |
| 1009 | |
| 1010 | /** Number of searches down the B-tree in btr_cur_search_to_nth_level(). */ |
| 1011 | extern ulint btr_cur_n_non_sea; |
| 1012 | /** Old value of btr_cur_n_non_sea. Copied by |
| 1013 | srv_refresh_innodb_monitor_stats(). Referenced by |
| 1014 | srv_printf_innodb_monitor(). */ |
| 1015 | extern ulint btr_cur_n_non_sea_old; |
| 1016 | #ifdef BTR_CUR_HASH_ADAPT |
| 1017 | /** Number of successful adaptive hash index lookups in |
| 1018 | btr_cur_search_to_nth_level(). */ |
| 1019 | extern ulint btr_cur_n_sea; |
| 1020 | /** Old value of btr_cur_n_sea. Copied by |
| 1021 | srv_refresh_innodb_monitor_stats(). Referenced by |
| 1022 | srv_printf_innodb_monitor(). */ |
| 1023 | extern ulint btr_cur_n_sea_old; |
| 1024 | #endif /* BTR_CUR_HASH_ADAPT */ |
| 1025 | |
| 1026 | #ifdef UNIV_DEBUG |
| 1027 | /* Flag to limit optimistic insert records */ |
| 1028 | extern uint btr_cur_limit_optimistic_insert_debug; |
| 1029 | #endif /* UNIV_DEBUG */ |
| 1030 | |
| 1031 | #include "btr0cur.ic" |
| 1032 | |
| 1033 | #endif |
| 1034 | |