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