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