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