1/***************************************************************************** 2 3Copyright (c) 1994, 2014, Oracle and/or its affiliates. All Rights Reserved. 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/*********************************************************//** 98Invalidates a tree cursor by setting record pointer to NULL. */ 99UNIV_INLINE 100void 101btr_cur_invalidate( 102/*===============*/ 103 btr_cur_t* cursor) /*!< in: tree cursor */ 104{ 105 page_cur_invalidate(&(cursor->page_cur)); 106} 107 108/*********************************************************//** 109Returns the page of a tree cursor. 110@return pointer to page */ 111UNIV_INLINE 112page_t* 113btr_cur_get_page( 114/*=============*/ 115 btr_cur_t* cursor) /*!< in: tree cursor */ 116{ 117 return(page_align(page_cur_get_rec(&(cursor->page_cur)))); 118} 119 120/*********************************************************//** 121Positions a tree cursor at a given record. */ 122UNIV_INLINE 123void 124btr_cur_position( 125/*=============*/ 126 dict_index_t* index, /*!< in: index */ 127 rec_t* rec, /*!< in: record in tree */ 128 buf_block_t* block, /*!< in: buffer block of rec */ 129 btr_cur_t* cursor) /*!< out: cursor */ 130{ 131 ut_ad(page_align(rec) == block->frame); 132 133 page_cur_position(rec, block, btr_cur_get_page_cur(cursor)); 134 135 cursor->index = index; 136} 137 138/*********************************************************************//** 139Checks if compressing an index page where a btr cursor is placed makes 140sense. 141@return TRUE if compression is recommended */ 142UNIV_INLINE 143ibool 144btr_cur_compress_recommendation( 145/*============================*/ 146 btr_cur_t* cursor, /*!< in: btr cursor */ 147 mtr_t* mtr) /*!< in: mtr */ 148{ 149 const page_t* page; 150 151 ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor), 152 MTR_MEMO_PAGE_X_FIX)); 153 154 page = btr_cur_get_page(cursor); 155 156 LIMIT_OPTIMISTIC_INSERT_DEBUG(page_get_n_recs(page) * 2, 157 return(FALSE)); 158 159 if ((page_get_data_size(page) < BTR_CUR_PAGE_COMPRESS_LIMIT) 160 || ((btr_page_get_next(page, mtr) == FIL_NULL) 161 && (btr_page_get_prev(page, mtr) == FIL_NULL))) { 162 163 /* The page fillfactor has dropped below a predefined 164 minimum value OR the level in the B-tree contains just 165 one page: we recommend compression if this is not the 166 root page. */ 167 168 return(dict_index_get_page(cursor->index) 169 != page_get_page_no(page)); 170 } 171 172 return(FALSE); 173} 174 175/*********************************************************************//** 176Checks if the record on which the cursor is placed can be deleted without 177making tree compression necessary (or, recommended). 178@return TRUE if can be deleted without recommended compression */ 179UNIV_INLINE 180ibool 181btr_cur_can_delete_without_compress( 182/*================================*/ 183 btr_cur_t* cursor, /*!< in: btr cursor */ 184 ulint rec_size,/*!< in: rec_get_size(btr_cur_get_rec(cursor))*/ 185 mtr_t* mtr) /*!< in: mtr */ 186{ 187 page_t* page; 188 189 ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor), 190 MTR_MEMO_PAGE_X_FIX)); 191 192 page = btr_cur_get_page(cursor); 193 194 if ((page_get_data_size(page) - rec_size < BTR_CUR_PAGE_COMPRESS_LIMIT) 195 || ((btr_page_get_next(page, mtr) == FIL_NULL) 196 && (btr_page_get_prev(page, mtr) == FIL_NULL)) 197 || (page_get_n_recs(page) < 2)) { 198 199 /* The page fillfactor will drop below a predefined 200 minimum value, OR the level in the B-tree contains just 201 one page, OR the page will become empty: we recommend 202 compression if this is not the root page. */ 203 204 return(dict_index_get_page(cursor->index) 205 == page_get_page_no(page)); 206 } 207 208 return(TRUE); 209} 210 211/*******************************************************************//** 212Determine if an operation on off-page columns is an update. 213@return TRUE if op != BTR_STORE_INSERT */ 214UNIV_INLINE 215ibool 216btr_blob_op_is_update( 217/*==================*/ 218 enum blob_op op) /*!< in: operation */ 219{ 220 switch (op) { 221 case BTR_STORE_INSERT: 222 return(FALSE); 223 case BTR_STORE_INSERT_UPDATE: 224 case BTR_STORE_UPDATE: 225 return(TRUE); 226 } 227 228 ut_ad(0); 229 return(FALSE); 230} 231#endif /* !UNIV_HOTBACKUP */ 232