1/***************************************************************************** 2 3Copyright (c) 1994, 2021, Oracle and/or its affiliates. 4 5This program is free software; you can redistribute it and/or modify 6it under the terms of the GNU General Public License, version 2.0, 7as published by the Free Software Foundation. 8 9This program is also distributed with certain software (including 10but not limited to OpenSSL) that is licensed under separate terms, 11as designated in a particular file or component or in included license 12documentation. The authors of MySQL hereby grant you an additional 13permission to link the program and your derivative works with the 14separately licensed software that they have included with MySQL. 15 16This program is distributed in the hope that it will be useful, 17but WITHOUT ANY WARRANTY; without even the implied warranty of 18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19GNU General Public License, version 2.0, for more details. 20 21You should have received a copy of the GNU General Public License along with 22this program; if not, write to the Free Software Foundation, Inc., 2351 Franklin Street, Suite 500, Boston, MA 02110-1335 USA 24 25*****************************************************************************/ 26 27/**************************************************//** 28@file include/btr0cur.ic 29The index tree cursor 30 31Created 10/16/1994 Heikki Tuuri 32*******************************************************/ 33 34#ifndef UNIV_HOTBACKUP 35#include "btr0btr.h" 36 37#ifdef UNIV_DEBUG 38# define LIMIT_OPTIMISTIC_INSERT_DEBUG(NREC, CODE)\ 39if (btr_cur_limit_optimistic_insert_debug > 1\ 40 && (NREC) >= (ulint)btr_cur_limit_optimistic_insert_debug) {\ 41 CODE;\ 42} 43#else 44# define LIMIT_OPTIMISTIC_INSERT_DEBUG(NREC, CODE) 45#endif /* UNIV_DEBUG */ 46 47#ifdef UNIV_DEBUG 48/*********************************************************//** 49Returns the page cursor component of a tree cursor. 50@return pointer to page cursor component */ 51UNIV_INLINE 52page_cur_t* 53btr_cur_get_page_cur( 54/*=================*/ 55 const btr_cur_t* cursor) /*!< in: tree cursor */ 56{ 57 return(&((btr_cur_t*) cursor)->page_cur); 58} 59 60/*********************************************************//** 61Returns the buffer block on which the tree cursor is positioned. 62@return pointer to buffer block */ 63UNIV_INLINE 64buf_block_t* 65btr_cur_get_block( 66/*==============*/ 67 const btr_cur_t* cursor) /*!< in: tree cursor */ 68{ 69 return(page_cur_get_block(btr_cur_get_page_cur(cursor))); 70} 71 72/*********************************************************//** 73Returns the record pointer of a tree cursor. 74@return pointer to record */ 75UNIV_INLINE 76rec_t* 77btr_cur_get_rec( 78/*============*/ 79 const btr_cur_t* cursor) /*!< in: tree cursor */ 80{ 81 return(page_cur_get_rec(btr_cur_get_page_cur(cursor))); 82} 83#endif /* UNIV_DEBUG */ 84 85/*********************************************************//** 86Returns the compressed page on which the tree cursor is positioned. 87@return pointer to compressed page, or NULL if the page is not compressed */ 88UNIV_INLINE 89page_zip_des_t* 90btr_cur_get_page_zip( 91/*=================*/ 92 btr_cur_t* cursor) /*!< in: tree cursor */ 93{ 94 return(buf_block_get_page_zip(btr_cur_get_block(cursor))); 95} 96 97/*********************************************************//** 98Returns the page of a tree cursor. 99@return pointer to page */ 100UNIV_INLINE 101page_t* 102btr_cur_get_page( 103/*=============*/ 104 btr_cur_t* cursor) /*!< in: tree cursor */ 105{ 106 return(page_align(page_cur_get_rec(&(cursor->page_cur)))); 107} 108 109/*********************************************************//** 110Positions a tree cursor at a given record. */ 111UNIV_INLINE 112void 113btr_cur_position( 114/*=============*/ 115 dict_index_t* index, /*!< in: index */ 116 rec_t* rec, /*!< in: record in tree */ 117 buf_block_t* block, /*!< in: buffer block of rec */ 118 btr_cur_t* cursor) /*!< out: cursor */ 119{ 120 ut_ad(page_align(rec) == block->frame); 121 122 page_cur_position(rec, block, btr_cur_get_page_cur(cursor)); 123 124 cursor->index = index; 125} 126 127/*********************************************************************//** 128Checks if compressing an index page where a btr cursor is placed makes 129sense. 130@return TRUE if compression is recommended */ 131UNIV_INLINE 132ibool 133btr_cur_compress_recommendation( 134/*============================*/ 135 btr_cur_t* cursor, /*!< in: btr cursor */ 136 mtr_t* mtr) /*!< in: mtr */ 137{ 138 const page_t* page; 139 140 ut_ad(mtr_is_block_fix( 141 mtr, btr_cur_get_block(cursor), 142 MTR_MEMO_PAGE_X_FIX, cursor->index->table)); 143 144 page = btr_cur_get_page(cursor); 145 146 LIMIT_OPTIMISTIC_INSERT_DEBUG(page_get_n_recs(page) * 2, 147 return(FALSE)); 148 149 if ((page_get_data_size(page) 150 < BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index)) 151 || ((btr_page_get_next(page, mtr) == FIL_NULL) 152 && (btr_page_get_prev(page, mtr) == FIL_NULL))) { 153 154 /* The page fillfactor has dropped below a predefined 155 minimum value OR the level in the B-tree contains just 156 one page: we recommend compression if this is not the 157 root page. */ 158 159 return(dict_index_get_page(cursor->index) 160 != page_get_page_no(page)); 161 } 162 163 return(FALSE); 164} 165 166/*********************************************************************//** 167Checks if the record on which the cursor is placed can be deleted without 168making tree compression necessary (or, recommended). 169@return TRUE if can be deleted without recommended compression */ 170UNIV_INLINE 171ibool 172btr_cur_can_delete_without_compress( 173/*================================*/ 174 btr_cur_t* cursor, /*!< in: btr cursor */ 175 ulint rec_size,/*!< in: rec_get_size(btr_cur_get_rec(cursor))*/ 176 mtr_t* mtr) /*!< in: mtr */ 177{ 178 page_t* page; 179 180 ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor), 181 MTR_MEMO_PAGE_X_FIX)); 182 183 page = btr_cur_get_page(cursor); 184 185 if ((page_get_data_size(page) - rec_size 186 < BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index)) 187 || ((btr_page_get_next(page, mtr) == FIL_NULL) 188 && (btr_page_get_prev(page, mtr) == FIL_NULL)) 189 || (page_get_n_recs(page) < 2)) { 190 191 /* The page fillfactor will drop below a predefined 192 minimum value, OR the level in the B-tree contains just 193 one page, OR the page will become empty: we recommend 194 compression if this is not the root page. */ 195 196 return(dict_index_get_page(cursor->index) 197 == page_get_page_no(page)); 198 } 199 200 return(TRUE); 201} 202 203/*******************************************************************//** 204Determine if an operation on off-page columns is an update. 205@return TRUE if op != BTR_STORE_INSERT */ 206UNIV_INLINE 207ibool 208btr_blob_op_is_update( 209/*==================*/ 210 enum blob_op op) /*!< in: operation */ 211{ 212 switch (op) { 213 case BTR_STORE_INSERT: 214 case BTR_STORE_INSERT_BULK: 215 return(FALSE); 216 case BTR_STORE_INSERT_UPDATE: 217 case BTR_STORE_UPDATE: 218 return(TRUE); 219 } 220 221 ut_ad(0); 222 return(FALSE); 223} 224 225/******************************************************//** 226The following function is used to set the deleted bit of a record. */ 227UNIV_INLINE 228void 229btr_rec_set_deleted_flag( 230/*=====================*/ 231 rec_t* rec, /*!< in/out: physical record */ 232 page_zip_des_t* page_zip,/*!< in/out: compressed page (or NULL) */ 233 ulint flag) /*!< in: nonzero if delete marked */ 234{ 235 if (page_rec_is_comp(rec)) { 236 rec_set_deleted_flag_new(rec, page_zip, flag); 237 } else { 238 ut_ad(!page_zip); 239 rec_set_deleted_flag_old(rec, flag); 240 } 241} 242 243#endif /* !UNIV_HOTBACKUP */ 244