1 /***************************************************************************** 2 3 Copyright (c) 1994, 2020, Oracle and/or its affiliates. All Rights Reserved. 4 5 This program is free software; you can redistribute it and/or modify it under 6 the terms of the GNU General Public License, version 2.0, as published by the 7 Free Software Foundation. 8 9 This program is also distributed with certain software (including but not 10 limited to OpenSSL) that is licensed under separate terms, as designated in a 11 particular file or component or in included license documentation. The authors 12 of MySQL hereby grant you an additional permission to link the program and 13 your derivative works with the separately licensed software that they have 14 included with MySQL. 15 16 This program is distributed in the hope that it will be useful, but WITHOUT 17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 18 FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0, 19 for more details. 20 21 You should have received a copy of the GNU General Public License along with 22 this program; if not, write to the Free Software Foundation, Inc., 23 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 25 *****************************************************************************/ 26 27 #include <stddef.h> 28 #include <sys/types.h> 29 30 /** @file include/btr0cur.h 31 The index tree cursor 32 33 Created 10/16/1994 Heikki Tuuri 34 *******************************************************/ 35 36 #ifndef btr0cur_h 37 #define btr0cur_h 38 39 #include "btr0types.h" 40 #include "dict0dict.h" 41 #include "gis0type.h" 42 #include "page0cur.h" 43 #include "univ.i" 44 45 /** Mode flags for btr_cur operations; these can be ORed */ 46 enum { 47 /** do no undo logging */ 48 BTR_NO_UNDO_LOG_FLAG = 1, 49 /** do no record lock checking */ 50 BTR_NO_LOCKING_FLAG = 2, 51 /** sys fields will be found in the update vector or inserted 52 entry */ 53 BTR_KEEP_SYS_FLAG = 4, 54 /** btr_cur_pessimistic_update() must keep cursor position 55 when moving columns to big_rec */ 56 BTR_KEEP_POS_FLAG = 8, 57 /** the caller is creating the index or wants to bypass the 58 index->info.online creation log */ 59 BTR_CREATE_FLAG = 16, 60 /** the caller of btr_cur_optimistic_update() or 61 btr_cur_update_in_place() will take care of 62 updating IBUF_BITMAP_FREE */ 63 BTR_KEEP_IBUF_BITMAP = 32 64 }; 65 66 /* btr_cur_latch_leaves() returns latched blocks and savepoints. */ 67 struct btr_latch_leaves_t { 68 /* left block, target block and right block */ 69 buf_block_t *blocks[3]; 70 ulint savepoints[3]; 71 }; 72 73 #ifndef UNIV_HOTBACKUP 74 #include "ha0ha.h" 75 #include "que0types.h" 76 #include "row0types.h" 77 #endif /* !UNIV_HOTBACKUP */ 78 79 #define BTR_CUR_ADAPT 80 #define BTR_CUR_HASH_ADAPT 81 82 #ifdef UNIV_DEBUG 83 /** Returns the page cursor component of a tree cursor. 84 @return pointer to page cursor component */ 85 UNIV_INLINE 86 page_cur_t *btr_cur_get_page_cur( 87 const btr_cur_t *cursor); /*!< in: tree cursor */ 88 /** Returns the buffer block on which the tree cursor is positioned. 89 @return pointer to buffer block */ 90 UNIV_INLINE 91 buf_block_t *btr_cur_get_block(const btr_cur_t *cursor); /*!< in: tree cursor */ 92 /** Returns the record pointer of a tree cursor. 93 @return pointer to record */ 94 UNIV_INLINE 95 rec_t *btr_cur_get_rec(const btr_cur_t *cursor); /*!< in: tree cursor */ 96 #else /* UNIV_DEBUG */ 97 #define btr_cur_get_page_cur(cursor) (&(cursor)->page_cur) 98 #define btr_cur_get_block(cursor) ((cursor)->page_cur.block) 99 #define btr_cur_get_rec(cursor) ((cursor)->page_cur.rec) 100 #endif /* UNIV_DEBUG */ 101 /** Returns the compressed page on which the tree cursor is positioned. 102 @return pointer to compressed page, or NULL if the page is not compressed */ 103 UNIV_INLINE 104 page_zip_des_t *btr_cur_get_page_zip(btr_cur_t *cursor); /*!< in: tree cursor */ 105 /** Returns the page of a tree cursor. 106 @return pointer to page */ 107 UNIV_INLINE 108 page_t *btr_cur_get_page(btr_cur_t *cursor); /*!< in: tree cursor */ 109 /** Returns the index of a cursor. 110 @param cursor b-tree cursor 111 @return index */ 112 #define btr_cur_get_index(cursor) ((cursor)->index) 113 114 /** Positions a tree cursor at a given record. 115 @param[in] index index 116 @param[in] rec record in tree 117 @param[in] block buffer block of rec 118 @param[in] cursor cursor */ 119 UNIV_INLINE 120 void btr_cur_position(dict_index_t *index, rec_t *rec, buf_block_t *block, 121 btr_cur_t *cursor); 122 123 /** Optimistically latches the leaf page or pages requested. 124 @param[in] block guessed buffer block 125 @param[in] modify_clock modify clock value 126 @param[in,out] latch_mode BTR_SEARCH_LEAF, ... 127 @param[in,out] cursor cursor 128 @param[in] file file name 129 @param[in] line line where called 130 @param[in] mtr mini-transaction 131 @return true if success */ 132 bool btr_cur_optimistic_latch_leaves(buf_block_t *block, 133 ib_uint64_t modify_clock, 134 ulint *latch_mode, btr_cur_t *cursor, 135 const char *file, ulint line, mtr_t *mtr); 136 137 /** Searches an index tree and positions a tree cursor on a given level. 138 NOTE: n_fields_cmp in tuple must be set so that it cannot be compared 139 to node pointer page number fields on the upper levels of the tree! 140 Note that if mode is PAGE_CUR_LE, which is used in inserts, then 141 cursor->up_match and cursor->low_match both will have sensible values. 142 If mode is PAGE_CUR_GE, then up_match will a have a sensible value. */ 143 void btr_cur_search_to_nth_level( 144 dict_index_t *index, /*!< in: index */ 145 ulint level, /*!< in: the tree level of search */ 146 const dtuple_t *tuple, /*!< in: data tuple; NOTE: n_fields_cmp in 147 tuple must be set so that it cannot get 148 compared to the node ptr page number field! */ 149 page_cur_mode_t mode, /*!< in: PAGE_CUR_L, ...; 150 NOTE that if the search is made using a unique 151 prefix of a record, mode should be PAGE_CUR_LE, 152 not PAGE_CUR_GE, as the latter may end up on 153 the previous page of the record! Inserts 154 should always be made using PAGE_CUR_LE to 155 search the position! */ 156 ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ..., ORed with 157 at most one of BTR_INSERT, BTR_DELETE_MARK, 158 BTR_DELETE, or BTR_ESTIMATE; 159 cursor->left_block is used to store a pointer 160 to the left neighbor page, in the cases 161 BTR_SEARCH_PREV and BTR_MODIFY_PREV; 162 NOTE that if has_search_latch 163 is != 0, we maybe do not have a latch set 164 on the cursor page, we assume 165 the caller uses his search latch 166 to protect the record! */ 167 btr_cur_t *cursor, /*!< in/out: tree cursor; the cursor page is 168 s- or x-latched, but see also above! */ 169 ulint has_search_latch, 170 /*!< in: latch mode the caller 171 currently has on search system: 172 RW_S_LATCH, or 0 */ 173 const char *file, /*!< in: file name */ 174 ulint line, /*!< in: line where called */ 175 mtr_t *mtr); /*!< in: mtr */ 176 177 /** Searches an index tree and positions a tree cursor on a given level. 178 This function will avoid placing latches the travesal path and so 179 should be used only for cases where-in latching is not needed. 180 181 @param[in] index index 182 @param[in] level the tree level of search 183 @param[in] tuple data tuple; Note: n_fields_cmp in compared 184 to the node ptr page node field 185 @param[in] mode PAGE_CUR_L, .... 186 Insert should always be made using PAGE_CUR_LE 187 to search the position. 188 @param[in,out] cursor tree cursor; points to record of interest. 189 @param[in] file file name 190 @param[in] line line where called from 191 @param[in,out] mtr mtr 192 @param[in] mark_dirty 193 if true then mark the block as dirty */ 194 void btr_cur_search_to_nth_level_with_no_latch( 195 dict_index_t *index, ulint level, const dtuple_t *tuple, 196 page_cur_mode_t mode, btr_cur_t *cursor, const char *file, ulint line, 197 mtr_t *mtr, bool mark_dirty = true); 198 199 /** Opens a cursor at either end of an index. */ 200 void btr_cur_open_at_index_side_func( 201 bool from_left, /*!< in: true if open to the low end, 202 false if to the high end */ 203 dict_index_t *index, /*!< in: index */ 204 ulint latch_mode, /*!< in: latch mode */ 205 btr_cur_t *cursor, /*!< in/out: cursor */ 206 ulint level, /*!< in: level to search for 207 (0=leaf) */ 208 const char *file, /*!< in: file name */ 209 ulint line, /*!< in: line where called */ 210 mtr_t *mtr); /*!< in/out: mini-transaction */ 211 #define btr_cur_open_at_index_side(f, i, l, c, lv, m) \ 212 btr_cur_open_at_index_side_func(f, i, l, c, lv, __FILE__, __LINE__, m) 213 214 /** Opens a cursor at either end of an index. 215 Avoid taking latches on buffer, just pin (by incrementing fix_count) 216 to keep them in buffer pool. This mode is used by intrinsic table 217 as they are not shared and so there is no need of latching. 218 @param[in] from_left true if open to low end, false if open 219 to high end. 220 @param[in] index index 221 @param[in,out] cursor cursor 222 @param[in] file file name 223 @param[in] line line where called 224 @param[in,out] mtr mini transaction 225 */ 226 void btr_cur_open_at_index_side_with_no_latch_func( 227 bool from_left, dict_index_t *index, btr_cur_t *cursor, ulint level, 228 const char *file, ulint line, mtr_t *mtr); 229 #define btr_cur_open_at_index_side_with_no_latch(f, i, c, lv, m) \ 230 btr_cur_open_at_index_side_with_no_latch_func(f, i, c, lv, __FILE__, \ 231 __LINE__, m) 232 233 /** Positions a cursor at a randomly chosen position within a B-tree. 234 @return true if the index is available and we have put the cursor, false 235 if the index is unavailable */ 236 bool btr_cur_open_at_rnd_pos_func( 237 dict_index_t *index, /*!< in: index */ 238 ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */ 239 btr_cur_t *cursor, /*!< in/out: B-tree cursor */ 240 const char *file, /*!< in: file name */ 241 ulint line, /*!< in: line where called */ 242 mtr_t *mtr); /*!< in: mtr */ 243 #define btr_cur_open_at_rnd_pos(i, l, c, m) \ 244 btr_cur_open_at_rnd_pos_func(i, l, c, __FILE__, __LINE__, m) 245 /** Tries to perform an insert to a page in an index tree, next to cursor. 246 It is assumed that mtr holds an x-latch on the page. The operation does 247 not succeed if there is too little space on the page. If there is just 248 one record on the page, the insert will always succeed; this is to 249 prevent trying to split a page with just one record. 250 @return DB_SUCCESS, DB_WAIT_LOCK, DB_FAIL, or error number */ 251 dberr_t btr_cur_optimistic_insert( 252 ulint flags, /*!< in: undo logging and locking flags: if not 253 zero, the parameters index and thr should be 254 specified */ 255 btr_cur_t *cursor, /*!< in: cursor on page after which to insert; 256 cursor stays valid */ 257 ulint **offsets, /*!< out: offsets on *rec */ 258 mem_heap_t **heap, /*!< in/out: pointer to memory heap, or NULL */ 259 dtuple_t *entry, /*!< in/out: entry to insert */ 260 rec_t **rec, /*!< out: pointer to inserted record if 261 succeed */ 262 big_rec_t **big_rec, /*!< out: big rec vector whose fields have to 263 be stored externally by the caller, or 264 NULL */ 265 que_thr_t *thr, /*!< in: query thread or NULL */ 266 mtr_t *mtr) /*!< in/out: mini-transaction; 267 if this function returns DB_SUCCESS on 268 a leaf page of a secondary index in a 269 compressed tablespace, the caller must 270 mtr_commit(mtr) before latching 271 any further pages */ 272 MY_ATTRIBUTE((warn_unused_result)); 273 /** Performs an insert on a page of an index tree. It is assumed that mtr 274 holds an x-latch on the tree and on the cursor page. If the insert is 275 made on the leaf level, to avoid deadlocks, mtr must also own x-latches 276 to brothers of page, if those brothers exist. 277 @return DB_SUCCESS or error number */ 278 dberr_t btr_cur_pessimistic_insert( 279 uint32_t flags, /*!< in: undo logging and locking flags: if not 280 zero, the parameter thr should be 281 specified; if no undo logging is specified, 282 then the caller must have reserved enough 283 free extents in the file space so that the 284 insertion will certainly succeed */ 285 btr_cur_t *cursor, /*!< in: cursor after which to insert; 286 cursor stays valid */ 287 ulint **offsets, /*!< out: offsets on *rec */ 288 mem_heap_t **heap, /*!< in/out: pointer to memory heap 289 that can be emptied, or NULL */ 290 dtuple_t *entry, /*!< in/out: entry to insert */ 291 rec_t **rec, /*!< out: pointer to inserted record if 292 succeed */ 293 big_rec_t **big_rec, /*!< out: big rec vector whose fields have to 294 be stored externally by the caller, or 295 NULL */ 296 que_thr_t *thr, /*!< in: query thread or NULL */ 297 mtr_t *mtr) /*!< in/out: mini-transaction */ 298 MY_ATTRIBUTE((warn_unused_result)); 299 /** See if there is enough place in the page modification log to log 300 an update-in-place. 301 302 @retval false if out of space; IBUF_BITMAP_FREE will be reset 303 outside mtr if the page was recompressed 304 @retval true if enough place; 305 306 IMPORTANT: The caller will have to update IBUF_BITMAP_FREE if this is 307 a secondary index leaf page. This has to be done either within the 308 same mini-transaction, or by invoking ibuf_reset_free_bits() before 309 mtr_commit(mtr). */ 310 bool btr_cur_update_alloc_zip_func( 311 page_zip_des_t *page_zip, /*!< in/out: compressed page */ 312 page_cur_t *cursor, /*!< in/out: B-tree page cursor */ 313 dict_index_t *index, /*!< in: the index corresponding to cursor */ 314 #ifdef UNIV_DEBUG 315 ulint *offsets, /*!< in/out: offsets of the cursor record */ 316 #endif /* UNIV_DEBUG */ 317 ulint length, /*!< in: size needed */ 318 bool create, /*!< in: true=delete-and-insert, 319 false=update-in-place */ 320 mtr_t *mtr) /*!< in/out: mini-transaction */ 321 MY_ATTRIBUTE((warn_unused_result)); 322 #ifdef UNIV_DEBUG 323 #define btr_cur_update_alloc_zip(page_zip, cursor, index, offsets, len, cr, \ 324 mtr) \ 325 btr_cur_update_alloc_zip_func(page_zip, cursor, index, offsets, len, cr, mtr) 326 #else /* UNIV_DEBUG */ 327 #define btr_cur_update_alloc_zip(page_zip, cursor, index, offsets, len, cr, \ 328 mtr) \ 329 btr_cur_update_alloc_zip_func(page_zip, cursor, index, len, cr, mtr) 330 #endif /* UNIV_DEBUG */ 331 /** Updates a record when the update causes no size changes in its fields. 332 @return locking or undo log related error code, or 333 @retval DB_SUCCESS on success 334 @retval DB_ZIP_OVERFLOW if there is not enough space left 335 on the compressed page (IBUF_BITMAP_FREE was reset outside mtr) */ 336 dberr_t btr_cur_update_in_place( 337 ulint flags, /*!< in: undo logging and locking flags */ 338 btr_cur_t *cursor, /*!< in: cursor on the record to update; 339 cursor stays valid and positioned on the 340 same record */ 341 ulint *offsets, /*!< in/out: offsets on cursor->page_cur.rec */ 342 const upd_t *update, /*!< in: update vector */ 343 ulint cmpl_info, /*!< in: compiler info on secondary index 344 updates */ 345 que_thr_t *thr, /*!< in: query thread, or NULL if 346 flags & (BTR_NO_LOCKING_FLAG 347 | BTR_NO_UNDO_LOG_FLAG 348 | BTR_CREATE_FLAG 349 | BTR_KEEP_SYS_FLAG) */ 350 trx_id_t trx_id, /*!< in: transaction id */ 351 mtr_t *mtr) /*!< in/out: mini-transaction; if this 352 is a secondary index, the caller must 353 mtr_commit(mtr) before latching any 354 further pages */ 355 MY_ATTRIBUTE((warn_unused_result)); 356 /** Writes a redo log record of updating a record in-place. */ 357 void btr_cur_update_in_place_log( 358 ulint flags, /*!< in: undo logging and locking flags */ 359 const rec_t *rec, /*!< in: record */ 360 dict_index_t *index, /*!< in: index of the record */ 361 const upd_t *update, /*!< in: update vector */ 362 trx_id_t trx_id, /*!< in: transaction id */ 363 roll_ptr_t roll_ptr, /*!< in: roll ptr */ 364 mtr_t *mtr); /*!< in: mtr */ 365 /** Tries to update a record on a page in an index tree. It is assumed that mtr 366 holds an x-latch on the page. The operation does not succeed if there is too 367 little space on the page or if the update would result in too empty a page, 368 so that tree compression is recommended. 369 @return error code, including 370 @retval DB_SUCCESS on success 371 @retval DB_OVERFLOW if the updated record does not fit 372 @retval DB_UNDERFLOW if the page would become too empty 373 @retval DB_ZIP_OVERFLOW if there is not enough space left 374 on the compressed page */ 375 dberr_t btr_cur_optimistic_update( 376 ulint flags, /*!< in: undo logging and locking flags */ 377 btr_cur_t *cursor, /*!< in: cursor on the record to update; 378 cursor stays valid and positioned on the 379 same record */ 380 ulint **offsets, /*!< out: offsets on cursor->page_cur.rec */ 381 mem_heap_t **heap, /*!< in/out: pointer to NULL or memory heap */ 382 const upd_t *update, /*!< in: update vector; this must also 383 contain trx id and roll ptr fields */ 384 ulint cmpl_info, /*!< in: compiler info on secondary index 385 updates */ 386 que_thr_t *thr, /*!< in: query thread, or NULL if 387 flags & (BTR_NO_UNDO_LOG_FLAG 388 | BTR_NO_LOCKING_FLAG 389 | BTR_CREATE_FLAG 390 | BTR_KEEP_SYS_FLAG) */ 391 trx_id_t trx_id, /*!< in: transaction id */ 392 mtr_t *mtr) /*!< in/out: mini-transaction; if this 393 is a secondary index, the caller must 394 mtr_commit(mtr) before latching any 395 further pages */ 396 MY_ATTRIBUTE((warn_unused_result)); 397 398 /** Performs an update of a record on a page of a tree. It is assumed 399 that mtr holds an x-latch on the tree and on the cursor page. If the 400 update is made on the leaf level, to avoid deadlocks, mtr must also 401 own x-latches to brothers of page, if those brothers exist. 402 @param[in] flags undo logging, locking, and rollback flags 403 @param[in,out] cursor cursor on the record to update; 404 cursor may become invalid if *big_rec == NULL 405 || !(flags & BTR_KEEP_POS_FLAG) 406 @param[out] offsets offsets on cursor->page_cur.rec 407 @param[in,out] offsets_heap pointer to memory heap that can be emptied, 408 or NULL 409 @param[in,out] entry_heap memory heap for allocating big_rec and the 410 index tuple. 411 @param[out] big_rec big rec vector whose fields have to be stored 412 externally by the caller, or NULL 413 @param[in,out] update update vector; this is allowed to also contain 414 trx id and roll ptr fields. Non-updated columns 415 that are moved offpage will be appended to this. 416 @param[in] cmpl_info compiler info on secondary index updates 417 @param[in] thr query thread, or NULL if flags & 418 (BTR_NO_UNDO_LOG_FLAG | BTR_NO_LOCKING_FLAG | 419 BTR_CREATE_FLAG | BTR_KEEP_SYS_FLAG) 420 @param[in] trx_id transaction id 421 @param[in] undo_no undo number of the transaction. This is needed 422 for rollback to savepoint of partially updated LOB. 423 @param[in,out] mtr mini transaction; must be committed before latching 424 any further pages 425 @param[in] pcur the persistent cursor on the record to update. 426 @return DB_SUCCESS or error code */ 427 dberr_t btr_cur_pessimistic_update( 428 ulint flags, btr_cur_t *cursor, ulint **offsets, mem_heap_t **offsets_heap, 429 mem_heap_t *entry_heap, big_rec_t **big_rec, upd_t *update, ulint cmpl_info, 430 que_thr_t *thr, trx_id_t trx_id, undo_no_t undo_no, mtr_t *mtr, 431 btr_pcur_t *pcur = nullptr) MY_ATTRIBUTE((warn_unused_result)); 432 433 /** Marks a clustered index record deleted. Writes an undo log record to 434 undo log on this delete marking. Writes in the trx id field the id 435 of the deleting transaction, and in the roll ptr field pointer to the 436 undo log record created. 437 @return DB_SUCCESS, DB_LOCK_WAIT, or error number */ 438 dberr_t btr_cur_del_mark_set_clust_rec( 439 ulint flags, /*!< in: undo logging and locking flags */ 440 buf_block_t *block, /*!< in/out: buffer block of the record */ 441 rec_t *rec, /*!< in/out: record */ 442 dict_index_t *index, /*!< in: clustered index of the record */ 443 const ulint *offsets, /*!< in: rec_get_offsets(rec) */ 444 que_thr_t *thr, /*!< in: query thread */ 445 const dtuple_t *entry, /*!< in: dtuple for the deleting record */ 446 mtr_t *mtr) /*!< in/out: mini-transaction */ 447 MY_ATTRIBUTE((warn_unused_result)); 448 /** Sets a secondary index record delete mark to TRUE or FALSE. 449 @return DB_SUCCESS, DB_LOCK_WAIT, or error number */ 450 dberr_t btr_cur_del_mark_set_sec_rec( 451 ulint flags, /*!< in: locking flag */ 452 btr_cur_t *cursor, /*!< in: cursor */ 453 ibool val, /*!< in: value to set */ 454 que_thr_t *thr, /*!< in: query thread */ 455 mtr_t *mtr) /*!< in/out: mini-transaction */ 456 MY_ATTRIBUTE((warn_unused_result)); 457 /** Tries to compress a page of the tree if it seems useful. It is assumed 458 that mtr holds an x-latch on the tree and on the cursor page. To avoid 459 deadlocks, mtr must also own x-latches to brothers of page, if those 460 brothers exist. NOTE: it is assumed that the caller has reserved enough 461 free extents so that the compression will always succeed if done! 462 @return true if compression occurred */ 463 ibool btr_cur_compress_if_useful( 464 btr_cur_t *cursor, /*!< in/out: cursor on the page to compress; 465 cursor does not stay valid if compression 466 occurs */ 467 ibool adjust, /*!< in: TRUE if should adjust the 468 cursor position even if compression occurs */ 469 mtr_t *mtr); /*!< in/out: mini-transaction */ 470 /** Removes the record on which the tree cursor is positioned. It is assumed 471 that the mtr has an x-latch on the page where the cursor is positioned, 472 but no latch on the whole tree. 473 @return true if success, i.e., the page did not become too empty */ 474 ibool btr_cur_optimistic_delete_func( 475 btr_cur_t *cursor, /*!< in: cursor on the record to delete; 476 cursor stays valid: if deletion succeeds, 477 on function exit it points to the successor 478 of the deleted record */ 479 #ifdef UNIV_DEBUG 480 ulint flags, /*!< in: BTR_CREATE_FLAG or 0 */ 481 #endif /* UNIV_DEBUG */ 482 mtr_t *mtr) /*!< in: mtr; if this function returns 483 TRUE on a leaf page of a secondary 484 index, the mtr must be committed 485 before latching any further pages */ 486 MY_ATTRIBUTE((warn_unused_result)); 487 #ifdef UNIV_DEBUG 488 #define btr_cur_optimistic_delete(cursor, flags, mtr) \ 489 btr_cur_optimistic_delete_func(cursor, flags, mtr) 490 #else /* UNIV_DEBUG */ 491 #define btr_cur_optimistic_delete(cursor, flags, mtr) \ 492 btr_cur_optimistic_delete_func(cursor, mtr) 493 #endif /* UNIV_DEBUG */ 494 495 /** Removes the record on which the tree cursor is positioned. Tries 496 to compress the page if its fillfactor drops below a threshold 497 or if it is the only page on the level. It is assumed that mtr holds 498 an x-latch on the tree and on the cursor page. To avoid deadlocks, 499 mtr must also own x-latches to brothers of page, if those brothers 500 exist. 501 @param[out] err DB_SUCCESS or DB_OUT_OF_FILE_SPACE; the latter may occur 502 because we may have to update node pointers on upper 503 levels, and in the case of variable length keys these may 504 actually grow in size 505 @param[in] has_reserved_extents TRUE if the caller has already reserved 506 enough free extents so that he knows 507 that the operation will succeed 508 @param[in] cursor cursor on the record to delete; if compression does not 509 occur, the cursor stays valid: it points to successor of 510 deleted record on function exit 511 @param[in] flags BTR_CREATE_FLAG or 0 512 @param[in] rollback true if performing rollback, false otherwise. 513 @param[in] trx_id the current transaction id. 514 @param[in] undo_no undo number of the transaction. This is needed for rollback 515 to savepoint of partially updated LOB. 516 @param[in] rec_type undo record type. 517 @param[in] mtr the mini transaction 518 @param[in] pcur persistent cursor on the record to delete. 519 @return true if compression occurred */ 520 ibool btr_cur_pessimistic_delete(dberr_t *err, ibool has_reserved_extents, 521 btr_cur_t *cursor, uint32_t flags, 522 bool rollback, trx_id_t trx_id, 523 undo_no_t undo_no, ulint rec_type, mtr_t *mtr, 524 btr_pcur_t *pcur = nullptr); 525 526 /** Parses a redo log record of updating a record in-place. 527 @return end of log record or NULL */ 528 byte *btr_cur_parse_update_in_place( 529 byte *ptr, /*!< in: buffer */ 530 byte *end_ptr, /*!< in: buffer end */ 531 page_t *page, /*!< in/out: page or NULL */ 532 page_zip_des_t *page_zip, /*!< in/out: compressed page, or NULL */ 533 dict_index_t *index); /*!< in: index corresponding to page */ 534 /** Parses the redo log record for delete marking or unmarking of a clustered 535 index record. 536 @return end of log record or NULL */ 537 byte *btr_cur_parse_del_mark_set_clust_rec( 538 byte *ptr, /*!< in: buffer */ 539 byte *end_ptr, /*!< in: buffer end */ 540 page_t *page, /*!< in/out: page or NULL */ 541 page_zip_des_t *page_zip, /*!< in/out: compressed page, or NULL */ 542 dict_index_t *index); /*!< in: index corresponding to page */ 543 /** Parses the redo log record for delete marking or unmarking of a secondary 544 index record. 545 @return end of log record or NULL */ 546 byte *btr_cur_parse_del_mark_set_sec_rec( 547 byte *ptr, /*!< in: buffer */ 548 byte *end_ptr, /*!< in: buffer end */ 549 page_t *page, /*!< in/out: page or NULL */ 550 page_zip_des_t *page_zip); /*!< in/out: compressed page, or NULL */ 551 #ifndef UNIV_HOTBACKUP 552 553 /** Estimates the number of rows in a given index range. 554 @param[in] index index 555 @param[in] tuple1 range start, may also be empty tuple 556 @param[in] mode1 search mode for range start 557 @param[in] tuple2 range end, may also be empty tuple 558 @param[in] mode2 search mode for range end 559 @return estimated number of rows */ 560 int64_t btr_estimate_n_rows_in_range(dict_index_t *index, 561 const dtuple_t *tuple1, 562 page_cur_mode_t mode1, 563 const dtuple_t *tuple2, 564 page_cur_mode_t mode2); 565 566 /** Estimates the number of different key values in a given index, for 567 each n-column prefix of the index where 1 <= n <= 568 dict_index_get_n_unique(index). The estimates are stored in the array 569 index->stat_n_diff_key_vals[] (indexed 0..n_uniq-1) and the number of pages 570 that were sampled is saved in index->stat_n_sample_sizes[]. If 571 innodb_stats_method is nulls_ignored, we also record the number of non-null 572 values for each prefix and stored the estimates in array 573 index->stat_n_non_null_key_vals. 574 @return true if the index is available and we get the estimated numbers, 575 false if the index is unavailable. */ 576 bool btr_estimate_number_of_different_key_vals( 577 dict_index_t *index); /*!< in: index */ 578 579 /** Copies an externally stored field of a record to mem heap. 580 @param[in] trx the trx doing the operation. 581 @param[in] index index containing the LOB. 582 @param[in] rec record in a clustered index; must be 583 protected by a lock or a page latch 584 @param[in] offsets array returned by rec_get_offsets() 585 @param[in] page_size BLOB page size 586 @param[in] no field number 587 @param[out] len length of the field 588 @param[out] lob_version version of lob */ 589 #ifdef UNIV_DEBUG 590 /** 591 @param[in] is_sdi true for SDI Indexes */ 592 #endif /* UNIV_DEBUG */ 593 /** 594 @param[in,out] heap mem heap 595 @return the field copied to heap, or NULL if the field is incomplete */ 596 byte *btr_rec_copy_externally_stored_field_func( 597 trx_t *trx, dict_index_t *index, const rec_t *rec, const ulint *offsets, 598 const page_size_t &page_size, ulint no, ulint *len, size_t *lob_version, 599 #ifdef UNIV_DEBUG 600 bool is_sdi, 601 #endif /* UNIV_DEBUG */ 602 mem_heap_t *heap); 603 604 /** Sets a secondary index record's delete mark to the given value. This 605 function is only used by the insert buffer merge mechanism. */ 606 void btr_cur_set_deleted_flag_for_ibuf( 607 rec_t *rec, /*!< in/out: record */ 608 page_zip_des_t *page_zip, /*!< in/out: compressed page 609 corresponding to rec, or NULL 610 when the tablespace is uncompressed */ 611 ibool val, /*!< in: value to set */ 612 mtr_t *mtr); /*!< in/out: mini-transaction */ 613 614 /** The following function is used to set the deleted bit of a record. 615 @param[in,out] rec physical record 616 @param[in,out] page_zip compressed page (or NULL) 617 @param[in] flag nonzero if delete marked */ 618 UNIV_INLINE 619 void btr_rec_set_deleted_flag(rec_t *rec, page_zip_des_t *page_zip, ulint flag); 620 621 /** Latches the leaf page or pages requested. 622 @param[in] block leaf page where the search converged 623 @param[in] page_id page id of the leaf 624 @param[in] latch_mode BTR_SEARCH_LEAF, ... 625 @param[in] cursor cursor 626 @param[in] mtr mini-transaction 627 @return blocks and savepoints which actually latched. */ 628 btr_latch_leaves_t btr_cur_latch_leaves(buf_block_t *block, 629 const page_id_t &page_id, 630 const page_size_t &page_size, 631 ulint latch_mode, btr_cur_t *cursor, 632 mtr_t *mtr); 633 #endif /* !UNIV_HOTBACKUP */ 634 635 /*######################################################################*/ 636 637 /** In the pessimistic delete, if the page data size drops below this 638 limit, merging it to a neighbor is tried */ 639 #define BTR_CUR_PAGE_COMPRESS_LIMIT(index) \ 640 ((UNIV_PAGE_SIZE * (ulint)((index)->merge_threshold)) / 100) 641 642 /** A slot in the path array. We store here info on a search path down the 643 tree. Each slot contains data on a single level of the tree. */ 644 struct btr_path_t { 645 /* Assume a page like: 646 records: (inf, a, b, c, d, sup) 647 index of the record: 0, 1, 2, 3, 4, 5 648 */ 649 650 /** Index of the record where the page cursor stopped on this level 651 (index in alphabetical order). Value ULINT_UNDEFINED denotes array 652 end. In the above example, if the search stopped on record 'c', then 653 nth_rec will be 3. */ 654 ulint nth_rec{ULINT_UNDEFINED}; 655 656 /** Number of the records on the page, not counting inf and sup. 657 In the above example n_recs will be 4. */ 658 ulint n_recs{ULINT_UNDEFINED}; 659 660 /** Number of the page containing the record. */ 661 page_no_t page_no{FIL_NULL}; 662 663 /** Level of the page. If later we fetch the page under page_no 664 and it is on a different level then we know that the tree has been 665 reorganized. */ 666 ulint page_level{ULINT_UNDEFINED}; 667 }; 668 669 #define BTR_PATH_ARRAY_N_SLOTS 250 /*!< size of path array (in slots) */ 670 671 /** Values for the flag documenting the used search method */ 672 enum btr_cur_method { 673 BTR_CUR_UNSET = 0, /*!< Flag for initialization only, 674 not in real use. */ 675 BTR_CUR_HASH = 1, /*!< successful shortcut using 676 the hash index */ 677 BTR_CUR_HASH_FAIL, /*!< failure using hash, success using 678 binary search: the misleading hash 679 reference is stored in the field 680 hash_node, and might be necessary to 681 update */ 682 BTR_CUR_BINARY, /*!< success using the binary search */ 683 BTR_CUR_INSERT_TO_IBUF, /*!< performed the intended insert to 684 the insert buffer */ 685 BTR_CUR_DEL_MARK_IBUF, /*!< performed the intended delete 686 mark in the insert/delete buffer */ 687 BTR_CUR_DELETE_IBUF, /*!< performed the intended delete in 688 the insert/delete buffer */ 689 BTR_CUR_DELETE_REF /*!< row_purge_poss_sec() failed */ 690 }; 691 692 /** The tree cursor: the definition appears here only for the compiler 693 to know struct size! */ 694 struct btr_cur_t { 695 dict_index_t *index{nullptr}; /*!< index where positioned */ 696 page_cur_t page_cur; /*!< page cursor */ 697 purge_node_t *purge_node{nullptr}; /*!< purge node, for BTR_DELETE */ 698 buf_block_t *left_block{nullptr}; /*!< this field is used to store 699 a pointer to the left neighbor 700 page, in the cases 701 BTR_SEARCH_PREV and 702 BTR_MODIFY_PREV */ 703 /*------------------------------*/ 704 que_thr_t *thr{nullptr}; /*!< this field is only used 705 when btr_cur_search_to_nth_level 706 is called for an index entry 707 insertion: the calling query 708 thread is passed here to be 709 used in the insert buffer */ 710 /*------------------------------*/ 711 /** The following fields are used in 712 btr_cur_search_to_nth_level to pass information: */ 713 /* @{ */ 714 btr_cur_method flag{BTR_CUR_UNSET}; /*!< Search method used */ 715 ulint tree_height{0}; /*!< Tree height if the search is done 716 for a pessimistic insert or update 717 operation */ 718 ulint up_match{0}; /*!< If the search mode was PAGE_CUR_LE, 719 the number of matched fields to the 720 the first user record to the right of 721 the cursor record after 722 btr_cur_search_to_nth_level; 723 for the mode PAGE_CUR_GE, the matched 724 fields to the first user record AT THE 725 CURSOR or to the right of it; 726 NOTE that the up_match and low_match 727 values may exceed the correct values 728 for comparison to the adjacent user 729 record if that record is on a 730 different leaf page! (See the note in 731 row_ins_duplicate_error_in_clust.) */ 732 ulint up_bytes{0}; /*!< number of matched bytes to the 733 right at the time cursor positioned; 734 only used internally in searches: not 735 defined after the search */ 736 ulint low_match{0}; /*!< if search mode was PAGE_CUR_LE, 737 the number of matched fields to the 738 first user record AT THE CURSOR or 739 to the left of it after 740 btr_cur_search_to_nth_level; 741 NOT defined for PAGE_CUR_GE or any 742 other search modes; see also the NOTE 743 in up_match! */ 744 ulint low_bytes{0}; /*!< number of matched bytes to the 745 left at the time cursor positioned; 746 only used internally in searches: not 747 defined after the search */ 748 ulint n_fields{0}; /*!< prefix length used in a hash 749 search if hash_node != NULL */ 750 ulint n_bytes{0}; /*!< hash prefix bytes if hash_node != 751 NULL */ 752 ulint fold{0}; /*!< fold value used in the search if 753 flag is BTR_CUR_HASH */ 754 /* @} */ 755 btr_path_t *path_arr{nullptr}; /*!< in estimating the number of 756 rows in range, we store in this array 757 information of the path through 758 the tree */ 759 rtr_info_t *rtr_info{nullptr}; /*!< rtree search info */ 760 761 /** Ownership of the above rtr_info member. */ 762 bool m_own_rtr_info = true; 763 764 /** If cursor is used in a scan or simple page fetch. */ 765 Page_fetch m_fetch_mode{Page_fetch::NORMAL}; 766 }; 767 768 /** The following function is used to set the deleted bit of a record. 769 @param[in,out] rec physical record 770 @param[in,out] page_zip compressed page (or NULL) 771 @param[in] flag nonzero if delete marked */ 772 UNIV_INLINE 773 void btr_rec_set_deleted_flag(rec_t *rec, page_zip_des_t *page_zip, ulint flag); 774 775 /** If pessimistic delete fails because of lack of file space, there 776 is still a good change of success a little later. Try this many 777 times. */ 778 #define BTR_CUR_RETRY_DELETE_N_TIMES 100 779 /** If pessimistic delete fails because of lack of file space, there 780 is still a good change of success a little later. Sleep this many 781 microseconds between retries. */ 782 #define BTR_CUR_RETRY_SLEEP_TIME 50000 783 784 /** Number of searches down the B-tree in btr_cur_search_to_nth_level(). */ 785 extern ulint btr_cur_n_non_sea; 786 /** Number of successful adaptive hash index lookups in 787 btr_cur_search_to_nth_level(). */ 788 extern ulint btr_cur_n_sea; 789 /** Old value of btr_cur_n_non_sea. Copied by 790 srv_refresh_innodb_monitor_stats(). Referenced by 791 srv_printf_innodb_monitor(). */ 792 extern ulint btr_cur_n_non_sea_old; 793 /** Old value of btr_cur_n_sea. Copied by 794 srv_refresh_innodb_monitor_stats(). Referenced by 795 srv_printf_innodb_monitor(). */ 796 extern ulint btr_cur_n_sea_old; 797 798 #ifdef UNIV_DEBUG 799 /* Flag to limit optimistic insert records */ 800 extern uint btr_cur_limit_optimistic_insert_debug; 801 #endif /* UNIV_DEBUG */ 802 803 #include "btr0cur.ic" 804 805 #endif 806