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