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