1 /***************************************************************************** 2 3 Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. 4 Copyright (c) 2018, MariaDB Corporation. 5 6 This program is free software; you can redistribute it and/or modify it under 7 the terms of the GNU General Public License as published by the Free Software 8 Foundation; version 2 of the License. 9 10 This program is distributed in the hope that it will be useful, but WITHOUT 11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License along with 15 this program; if not, write to the Free Software Foundation, Inc., 16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA 17 18 *****************************************************************************/ 19 20 /********************************************************************//** 21 @file include/page0cur.h 22 The page cursor 23 24 Created 10/4/1994 Heikki Tuuri 25 *************************************************************************/ 26 27 #ifndef page0cur_h 28 #define page0cur_h 29 30 #include "buf0types.h" 31 #include "page0page.h" 32 #include "rem0types.h" 33 #include "rem0rec.h" 34 #include "data0data.h" 35 #include "mtr0mtr.h" 36 #include "gis0type.h" 37 38 #ifdef UNIV_DEBUG 39 /*********************************************************//** 40 Gets pointer to the page frame where the cursor is positioned. 41 @return page */ 42 UNIV_INLINE 43 page_t* 44 page_cur_get_page( 45 /*==============*/ 46 page_cur_t* cur); /*!< in: page cursor */ 47 /*********************************************************//** 48 Gets pointer to the buffer block where the cursor is positioned. 49 @return page */ 50 UNIV_INLINE 51 buf_block_t* 52 page_cur_get_block( 53 /*===============*/ 54 page_cur_t* cur); /*!< in: page cursor */ 55 /*********************************************************//** 56 Gets pointer to the page frame where the cursor is positioned. 57 @return page */ 58 UNIV_INLINE 59 page_zip_des_t* 60 page_cur_get_page_zip( 61 /*==================*/ 62 page_cur_t* cur); /*!< in: page cursor */ 63 /*********************************************************//** 64 Gets the record where the cursor is positioned. 65 @return record */ 66 UNIV_INLINE 67 rec_t* 68 page_cur_get_rec( 69 /*=============*/ 70 page_cur_t* cur); /*!< in: page cursor */ 71 #else /* UNIV_DEBUG */ 72 # define page_cur_get_page(cur) page_align((cur)->rec) 73 # define page_cur_get_block(cur) (cur)->block 74 # define page_cur_get_page_zip(cur) buf_block_get_page_zip((cur)->block) 75 # define page_cur_get_rec(cur) (cur)->rec 76 #endif /* UNIV_DEBUG */ 77 /*********************************************************//** 78 Sets the cursor object to point before the first user record 79 on the page. */ 80 UNIV_INLINE 81 void 82 page_cur_set_before_first( 83 /*======================*/ 84 const buf_block_t* block, /*!< in: index page */ 85 page_cur_t* cur); /*!< in: cursor */ 86 /*********************************************************//** 87 Sets the cursor object to point after the last user record on 88 the page. */ 89 UNIV_INLINE 90 void 91 page_cur_set_after_last( 92 /*====================*/ 93 const buf_block_t* block, /*!< in: index page */ 94 page_cur_t* cur); /*!< in: cursor */ 95 /*********************************************************//** 96 Returns TRUE if the cursor is before first user record on page. 97 @return TRUE if at start */ 98 UNIV_INLINE 99 ibool 100 page_cur_is_before_first( 101 /*=====================*/ 102 const page_cur_t* cur); /*!< in: cursor */ 103 /*********************************************************//** 104 Returns TRUE if the cursor is after last user record. 105 @return TRUE if at end */ 106 UNIV_INLINE 107 ibool 108 page_cur_is_after_last( 109 /*===================*/ 110 const page_cur_t* cur); /*!< in: cursor */ 111 /**********************************************************//** 112 Positions the cursor on the given record. */ 113 UNIV_INLINE 114 void 115 page_cur_position( 116 /*==============*/ 117 const rec_t* rec, /*!< in: record on a page */ 118 const buf_block_t* block, /*!< in: buffer block containing 119 the record */ 120 page_cur_t* cur); /*!< out: page cursor */ 121 /**********************************************************//** 122 Moves the cursor to the next record on page. */ 123 UNIV_INLINE 124 void 125 page_cur_move_to_next( 126 /*==================*/ 127 page_cur_t* cur); /*!< in/out: cursor; must not be after last */ 128 /**********************************************************//** 129 Moves the cursor to the previous record on page. */ 130 UNIV_INLINE 131 void 132 page_cur_move_to_prev( 133 /*==================*/ 134 page_cur_t* cur); /*!< in/out: cursor; not before first */ 135 136 /***********************************************************//** 137 Inserts a record next to page cursor. Returns pointer to inserted record if 138 succeed, i.e., enough space available, NULL otherwise. The cursor stays at 139 the same logical position, but the physical position may change if it is 140 pointing to a compressed page that was reorganized. 141 142 IMPORTANT: The caller will have to update IBUF_BITMAP_FREE 143 if this is a compressed leaf page in a secondary index. 144 This has to be done either within the same mini-transaction, 145 or by invoking ibuf_reset_free_bits() before mtr_commit(). 146 147 @return pointer to record if succeed, NULL otherwise */ 148 UNIV_INLINE 149 rec_t* 150 page_cur_tuple_insert( 151 /*==================*/ 152 page_cur_t* cursor, /*!< in/out: a page cursor */ 153 const dtuple_t* tuple, /*!< in: pointer to a data tuple */ 154 dict_index_t* index, /*!< in: record descriptor */ 155 rec_offs** offsets,/*!< out: offsets on *rec */ 156 mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */ 157 ulint n_ext, /*!< in: number of externally stored columns */ 158 mtr_t* mtr) /*!< in: mini-transaction handle, or NULL */ 159 MY_ATTRIBUTE((nonnull(1,2,3,4,5), warn_unused_result)); 160 /***********************************************************//** 161 Inserts a record next to page cursor. Returns pointer to inserted record if 162 succeed, i.e., enough space available, NULL otherwise. The cursor stays at 163 the same logical position, but the physical position may change if it is 164 pointing to a compressed page that was reorganized. 165 166 IMPORTANT: The caller will have to update IBUF_BITMAP_FREE 167 if this is a compressed leaf page in a secondary index. 168 This has to be done either within the same mini-transaction, 169 or by invoking ibuf_reset_free_bits() before mtr_commit(). 170 171 @return pointer to record if succeed, NULL otherwise */ 172 UNIV_INLINE 173 rec_t* 174 page_cur_rec_insert( 175 /*================*/ 176 page_cur_t* cursor, /*!< in/out: a page cursor */ 177 const rec_t* rec, /*!< in: record to insert */ 178 dict_index_t* index, /*!< in: record descriptor */ 179 rec_offs* offsets,/*!< in/out: rec_get_offsets(rec, index) */ 180 mtr_t* mtr); /*!< in: mini-transaction handle, or NULL */ 181 /***********************************************************//** 182 Inserts a record next to page cursor on an uncompressed page. 183 Returns pointer to inserted record if succeed, i.e., enough 184 space available, NULL otherwise. The cursor stays at the same position. 185 @return pointer to record if succeed, NULL otherwise */ 186 rec_t* 187 page_cur_insert_rec_low( 188 /*====================*/ 189 rec_t* current_rec,/*!< in: pointer to current record after 190 which the new record is inserted */ 191 dict_index_t* index, /*!< in: record descriptor */ 192 const rec_t* rec, /*!< in: pointer to a physical record */ 193 rec_offs* offsets,/*!< in/out: rec_get_offsets(rec, index) */ 194 mtr_t* mtr) /*!< in: mini-transaction handle, or NULL */ 195 MY_ATTRIBUTE((nonnull(1,2,3,4), warn_unused_result)); 196 197 /***********************************************************//** 198 Inserts a record next to page cursor on a compressed and uncompressed 199 page. Returns pointer to inserted record if succeed, i.e., 200 enough space available, NULL otherwise. 201 The cursor stays at the same position. 202 203 IMPORTANT: The caller will have to update IBUF_BITMAP_FREE 204 if this is a compressed leaf page in a secondary index. 205 This has to be done either within the same mini-transaction, 206 or by invoking ibuf_reset_free_bits() before mtr_commit(). 207 208 @return pointer to record if succeed, NULL otherwise */ 209 rec_t* 210 page_cur_insert_rec_zip( 211 /*====================*/ 212 page_cur_t* cursor, /*!< in/out: page cursor */ 213 dict_index_t* index, /*!< in: record descriptor */ 214 const rec_t* rec, /*!< in: pointer to a physical record */ 215 rec_offs* offsets,/*!< in/out: rec_get_offsets(rec, index) */ 216 mtr_t* mtr) /*!< in: mini-transaction handle, or NULL */ 217 MY_ATTRIBUTE((nonnull(1,2,3,4), warn_unused_result)); 218 /*************************************************************//** 219 Copies records from page to a newly created page, from a given record onward, 220 including that record. Infimum and supremum records are not copied. 221 222 IMPORTANT: The caller will have to update IBUF_BITMAP_FREE 223 if this is a compressed leaf page in a secondary index. 224 This has to be done either within the same mini-transaction, 225 or by invoking ibuf_reset_free_bits() before mtr_commit(). */ 226 void 227 page_copy_rec_list_end_to_created_page( 228 /*===================================*/ 229 page_t* new_page, /*!< in/out: index page to copy to */ 230 rec_t* rec, /*!< in: first record to copy */ 231 dict_index_t* index, /*!< in: record descriptor */ 232 mtr_t* mtr); /*!< in: mtr */ 233 /***********************************************************//** 234 Deletes a record at the page cursor. The cursor is moved to the 235 next record after the deleted one. */ 236 void 237 page_cur_delete_rec( 238 /*================*/ 239 page_cur_t* cursor, /*!< in/out: a page cursor */ 240 const dict_index_t* index, /*!< in: record descriptor */ 241 const rec_offs* offsets,/*!< in: rec_get_offsets( 242 cursor->rec, index) */ 243 mtr_t* mtr); /*!< in: mini-transaction handle */ 244 245 /** Search the right position for a page cursor. 246 @param[in] block buffer block 247 @param[in] index index tree 248 @param[in] tuple data tuple 249 @param[in] mode PAGE_CUR_L, PAGE_CUR_LE, PAGE_CUR_G, or PAGE_CUR_GE 250 @param[out] cursor page cursor 251 @return number of matched fields on the left */ 252 UNIV_INLINE 253 ulint 254 page_cur_search( 255 const buf_block_t* block, 256 const dict_index_t* index, 257 const dtuple_t* tuple, 258 page_cur_mode_t mode, 259 page_cur_t* cursor); 260 261 /** Search the right position for a page cursor. 262 @param[in] block buffer block 263 @param[in] index index tree 264 @param[in] tuple data tuple 265 @param[out] cursor page cursor 266 @return number of matched fields on the left */ 267 UNIV_INLINE 268 ulint 269 page_cur_search( 270 const buf_block_t* block, 271 const dict_index_t* index, 272 const dtuple_t* tuple, 273 page_cur_t* cursor); 274 275 /****************************************************************//** 276 Searches the right position for a page cursor. */ 277 void 278 page_cur_search_with_match( 279 /*=======================*/ 280 const buf_block_t* block, /*!< in: buffer block */ 281 const dict_index_t* index, /*!< in: record descriptor */ 282 const dtuple_t* tuple, /*!< in: data tuple */ 283 page_cur_mode_t mode, /*!< in: PAGE_CUR_L, 284 PAGE_CUR_LE, PAGE_CUR_G, or 285 PAGE_CUR_GE */ 286 ulint* iup_matched_fields, 287 /*!< in/out: already matched 288 fields in upper limit record */ 289 ulint* ilow_matched_fields, 290 /*!< in/out: already matched 291 fields in lower limit record */ 292 page_cur_t* cursor, /*!< out: page cursor */ 293 rtr_info_t* rtr_info);/*!< in/out: rtree search stack */ 294 #ifdef BTR_CUR_HASH_ADAPT 295 /** Search the right position for a page cursor. 296 @param[in] block buffer block 297 @param[in] index index tree 298 @param[in] tuple key to be searched for 299 @param[in] mode search mode 300 @param[in,out] iup_matched_fields already matched fields in the 301 upper limit record 302 @param[in,out] iup_matched_bytes already matched bytes in the 303 first partially matched field in the upper limit record 304 @param[in,out] ilow_matched_fields already matched fields in the 305 lower limit record 306 @param[in,out] ilow_matched_bytes already matched bytes in the 307 first partially matched field in the lower limit record 308 @param[out] cursor page cursor */ 309 void 310 page_cur_search_with_match_bytes( 311 const buf_block_t* block, 312 const dict_index_t* index, 313 const dtuple_t* tuple, 314 page_cur_mode_t mode, 315 ulint* iup_matched_fields, 316 ulint* iup_matched_bytes, 317 ulint* ilow_matched_fields, 318 ulint* ilow_matched_bytes, 319 page_cur_t* cursor); 320 #endif /* BTR_CUR_HASH_ADAPT */ 321 /***********************************************************//** 322 Positions a page cursor on a randomly chosen user record on a page. If there 323 are no user records, sets the cursor on the infimum record. */ 324 void 325 page_cur_open_on_rnd_user_rec( 326 /*==========================*/ 327 buf_block_t* block, /*!< in: page */ 328 page_cur_t* cursor);/*!< out: page cursor */ 329 /** Write a redo log record of inserting a record into an index page. 330 @param[in] insert_rec inserted record 331 @param[in] rec_size rec_get_size(insert_rec) 332 @param[in] cursor_rec predecessor of insert_rec 333 @param[in,out] index index tree 334 @param[in,out] mtr mini-transaction */ 335 void 336 page_cur_insert_rec_write_log( 337 const rec_t* insert_rec, 338 ulint rec_size, 339 const rec_t* cursor_rec, 340 dict_index_t* index, 341 mtr_t* mtr) 342 MY_ATTRIBUTE((nonnull)); 343 /***********************************************************//** 344 Parses a log record of a record insert on a page. 345 @return end of log record or NULL */ 346 byte* 347 page_cur_parse_insert_rec( 348 /*======================*/ 349 ibool is_short,/*!< in: TRUE if short inserts */ 350 const byte* ptr, /*!< in: buffer */ 351 const byte* end_ptr,/*!< in: buffer end */ 352 buf_block_t* block, /*!< in: page or NULL */ 353 dict_index_t* index, /*!< in: record descriptor */ 354 mtr_t* mtr); /*!< in: mtr or NULL */ 355 /**********************************************************//** 356 Parses a log record of copying a record list end to a new created page. 357 @return end of log record or NULL */ 358 byte* 359 page_parse_copy_rec_list_to_created_page( 360 /*=====================================*/ 361 byte* ptr, /*!< in: buffer */ 362 byte* end_ptr,/*!< in: buffer end */ 363 buf_block_t* block, /*!< in: page or NULL */ 364 dict_index_t* index, /*!< in: record descriptor */ 365 mtr_t* mtr); /*!< in: mtr or NULL */ 366 /***********************************************************//** 367 Parses log record of a record delete on a page. 368 @return pointer to record end or NULL */ 369 byte* 370 page_cur_parse_delete_rec( 371 /*======================*/ 372 byte* ptr, /*!< in: buffer */ 373 byte* end_ptr,/*!< in: buffer end */ 374 buf_block_t* block, /*!< in: page or NULL */ 375 dict_index_t* index, /*!< in: record descriptor */ 376 mtr_t* mtr); /*!< in: mtr or NULL */ 377 /*******************************************************//** 378 Removes the record from a leaf page. This function does not log 379 any changes. It is used by the IMPORT tablespace functions. 380 @return true if success, i.e., the page did not become too empty */ 381 bool 382 page_delete_rec( 383 /*============*/ 384 const dict_index_t* index, /*!< in: The index that the record 385 belongs to */ 386 page_cur_t* pcur, /*!< in/out: page cursor on record 387 to delete */ 388 page_zip_des_t* page_zip,/*!< in: compressed page descriptor */ 389 const rec_offs* offsets);/*!< in: offsets for record */ 390 391 /** Index page cursor */ 392 393 struct page_cur_t{ 394 const dict_index_t* index; 395 rec_t* rec; /*!< pointer to a record on page */ 396 rec_offs* offsets; 397 buf_block_t* block; /*!< pointer to the block containing rec */ 398 }; 399 400 #include "page0cur.inl" 401 402 #endif 403