1 /*****************************************************************************
2 
3 Copyright (c) 1994, 2021, Oracle and/or its affiliates.
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/btr0cur.h
29 The index tree cursor
30 
31 Created 10/16/1994 Heikki Tuuri
32 *******************************************************/
33 
34 #ifndef btr0cur_h
35 #define btr0cur_h
36 
37 #include "univ.i"
38 #include "dict0dict.h"
39 #include "page0cur.h"
40 #include "btr0types.h"
41 #include "gis0type.h"
42 
43 /** Mode flags for btr_cur operations; these can be ORed */
44 enum {
45 	/** do no undo logging */
46 	BTR_NO_UNDO_LOG_FLAG = 1,
47 	/** do no record lock checking */
48 	BTR_NO_LOCKING_FLAG = 2,
49 	/** sys fields will be found in the update vector or inserted
50 	entry */
51 	BTR_KEEP_SYS_FLAG = 4,
52 	/** btr_cur_pessimistic_update() must keep cursor position
53 	when moving columns to big_rec */
54 	BTR_KEEP_POS_FLAG = 8,
55 	/** the caller is creating the index or wants to bypass the
56 	index->info.online creation log */
57 	BTR_CREATE_FLAG = 16,
58 	/** the caller of btr_cur_optimistic_update() or
59 	btr_cur_update_in_place() will take care of
60 	updating IBUF_BITMAP_FREE */
61 	BTR_KEEP_IBUF_BITMAP = 32
62 };
63 
64 /* btr_cur_latch_leaves() returns latched blocks and savepoints. */
65 struct btr_latch_leaves_t {
66 	/* left block, target block and right block */
67 	buf_block_t*	blocks[3];
68 	ulint		savepoints[3];
69 };
70 
71 #ifndef UNIV_HOTBACKUP
72 #include "que0types.h"
73 #include "row0types.h"
74 #include "ha0ha.h"
75 
76 #ifdef UNIV_DEBUG
77 /*********************************************************//**
78 Returns the page cursor component of a tree cursor.
79 @return pointer to page cursor component */
80 UNIV_INLINE
81 page_cur_t*
82 btr_cur_get_page_cur(
83 /*=================*/
84 	const btr_cur_t*	cursor);/*!< in: tree cursor */
85 /*********************************************************//**
86 Returns the buffer block on which the tree cursor is positioned.
87 @return pointer to buffer block */
88 UNIV_INLINE
89 buf_block_t*
90 btr_cur_get_block(
91 /*==============*/
92 	const btr_cur_t*	cursor);/*!< in: tree cursor */
93 /*********************************************************//**
94 Returns the record pointer of a tree cursor.
95 @return pointer to record */
96 UNIV_INLINE
97 rec_t*
98 btr_cur_get_rec(
99 /*============*/
100 	const btr_cur_t*	cursor);/*!< in: tree cursor */
101 #else /* UNIV_DEBUG */
102 # define btr_cur_get_page_cur(cursor)	(&(cursor)->page_cur)
103 # define btr_cur_get_block(cursor)	((cursor)->page_cur.block)
104 # define btr_cur_get_rec(cursor)	((cursor)->page_cur.rec)
105 #endif /* UNIV_DEBUG */
106 /*********************************************************//**
107 Returns the compressed page on which the tree cursor is positioned.
108 @return pointer to compressed page, or NULL if the page is not compressed */
109 UNIV_INLINE
110 page_zip_des_t*
111 btr_cur_get_page_zip(
112 /*=================*/
113 	btr_cur_t*	cursor);/*!< in: tree cursor */
114 /*********************************************************//**
115 Returns the page of a tree cursor.
116 @return pointer to page */
117 UNIV_INLINE
118 page_t*
119 btr_cur_get_page(
120 /*=============*/
121 	btr_cur_t*	cursor);/*!< in: tree cursor */
122 /*********************************************************//**
123 Returns the index of a cursor.
124 @param cursor b-tree cursor
125 @return index */
126 #define btr_cur_get_index(cursor) ((cursor)->index)
127 /*********************************************************//**
128 Positions a tree cursor at a given record. */
129 UNIV_INLINE
130 void
131 btr_cur_position(
132 /*=============*/
133 	dict_index_t*	index,	/*!< in: index */
134 	rec_t*		rec,	/*!< in: record in tree */
135 	buf_block_t*	block,	/*!< in: buffer block of rec */
136 	btr_cur_t*	cursor);/*!< in: cursor */
137 
138 /** Optimistically latches the leaf page or pages requested.
139 @param[in]	block		guessed buffer block
140 @param[in]	modify_clock	modify clock value
141 @param[in,out]	latch_mode	BTR_SEARCH_LEAF, ...
142 @param[in,out]	cursor		cursor
143 @param[in]	file		file name
144 @param[in]	line		line where called
145 @param[in]	mtr		mini-transaction
146 @return true if success */
147 bool
148 btr_cur_optimistic_latch_leaves(
149 	buf_block_t*	block,
150 	ib_uint64_t	modify_clock,
151 	ulint*		latch_mode,
152 	btr_cur_t*	cursor,
153 	const char*	file,
154 	ulint		line,
155 	mtr_t*		mtr);
156 
157 /********************************************************************//**
158 Searches an index tree and positions a tree cursor on a given level.
159 NOTE: n_fields_cmp in tuple must be set so that it cannot be compared
160 to node pointer page number fields on the upper levels of the tree!
161 Note that if mode is PAGE_CUR_LE, which is used in inserts, then
162 cursor->up_match and cursor->low_match both will have sensible values.
163 If mode is PAGE_CUR_GE, then up_match will a have a sensible value. */
164 dberr_t
165 btr_cur_search_to_nth_level(
166 /*========================*/
167 	dict_index_t*	index,	/*!< in: index */
168 	ulint		level,	/*!< in: the tree level of search */
169 	const dtuple_t*	tuple,	/*!< in: data tuple; NOTE: n_fields_cmp in
170 				tuple must be set so that it cannot get
171 				compared to the node ptr page number field! */
172 	page_cur_mode_t	mode,	/*!< in: PAGE_CUR_L, ...;
173 				NOTE that if the search is made using a unique
174 				prefix of a record, mode should be PAGE_CUR_LE,
175 				not PAGE_CUR_GE, as the latter may end up on
176 				the previous page of the record! Inserts
177 				should always be made using PAGE_CUR_LE to
178 				search the position! */
179 	ulint		latch_mode, /*!< in: BTR_SEARCH_LEAF, ..., ORed with
180 				at most one of BTR_INSERT, BTR_DELETE_MARK,
181 				BTR_DELETE, or BTR_ESTIMATE;
182 				cursor->left_block is used to store a pointer
183 				to the left neighbor page, in the cases
184 				BTR_SEARCH_PREV and BTR_MODIFY_PREV;
185 				NOTE that if has_search_latch
186 				is != 0, we maybe do not have a latch set
187 				on the cursor page, we assume
188 				the caller uses his search latch
189 				to protect the record! */
190 	btr_cur_t*	cursor, /*!< in/out: tree cursor; the cursor page is
191 				s- or x-latched, but see also above! */
192 	ulint		has_search_latch,
193 				/*!< in: latch mode the caller
194 				currently has on search system:
195 				RW_S_LATCH, or 0 */
196 	const char*	file,	/*!< in: file name */
197 	ulint		line,	/*!< in: line where called */
198 	mtr_t*		mtr);	/*!< in: mtr */
199 
200 /** Searches an index tree and positions a tree cursor on a given level.
201 This function will avoid placing latches the travesal path and so
202 should be used only for cases where-in latching is not needed.
203 
204 @param[in]	index	index
205 @param[in]	level	the tree level of search
206 @param[in]	tuple	data tuple; Note: n_fields_cmp in compared
207 			to the node ptr page node field
208 @param[in]	mode	PAGE_CUR_L, ....
209 			Insert should always be made using PAGE_CUR_LE
210 			to search the position.
211 @param[in,out]	cursor	tree cursor; points to record of interest.
212 @param[in]	file	file name
213 @param[in[	line	line where called from
214 @param[in,out]	mtr	mtr
215 @param[in]	mark_dirty
216 			if true then mark the block as dirty */
217 void
218 btr_cur_search_to_nth_level_with_no_latch(
219 	dict_index_t*		index,
220 	ulint			level,
221 	const dtuple_t*		tuple,
222 	page_cur_mode_t		mode,
223 	btr_cur_t*		cursor,
224 	const char*		file,
225 	ulint			line,
226 	mtr_t*			mtr,
227 	bool			mark_dirty = true);
228 
229 /*****************************************************************//**
230 Opens a cursor at either end of an index. */
231 dberr_t
232 btr_cur_open_at_index_side_func(
233 /*============================*/
234 	bool		from_left,	/*!< in: true if open to the low end,
235 					false if to the high end */
236 	dict_index_t*	index,		/*!< in: index */
237 	ulint		latch_mode,	/*!< in: latch mode */
238 	btr_cur_t*	cursor,		/*!< in/out: cursor */
239 	ulint		level,		/*!< in: level to search for
240 					(0=leaf) */
241 	const char*	file,		/*!< in: file name */
242 	ulint		line,		/*!< in: line where called */
243 	mtr_t*		mtr);		/*!< in/out: mini-transaction */
244 #define btr_cur_open_at_index_side(f,i,l,c,lv,m)			\
245 	btr_cur_open_at_index_side_func(f,i,l,c,lv,__FILE__,__LINE__,m)
246 
247 /** Opens a cursor at either end of an index.
248 Avoid taking latches on buffer, just pin (by incrementing fix_count)
249 to keep them in buffer pool. This mode is used by intrinsic table
250 as they are not shared and so there is no need of latching.
251 @param[in]	from_left	true if open to low end, false if open
252 				to high end.
253 @param[in]	index		index
254 @param[in]	latch_mode	latch mode
255 @param[in,out]	cursor		cursor
256 @param[in]	file		file name
257 @param[in]	line		line where called
258 @param[in,out]	mtr		mini transaction
259 */
260 void
261 btr_cur_open_at_index_side_with_no_latch_func(
262 	bool		from_left,
263 	dict_index_t*	index,
264 	btr_cur_t*	cursor,
265 	ulint		level,
266 	const char*	file,
267 	ulint		line,
268 	mtr_t*		mtr);
269 #define btr_cur_open_at_index_side_with_no_latch(f,i,c,lv,m)		\
270 	btr_cur_open_at_index_side_with_no_latch_func(			\
271 		f,i,c,lv,__FILE__,__LINE__,m)
272 
273 /**********************************************************************//**
274 Positions a cursor at a randomly chosen position within a B-tree.
275 @return true if the index is available and we have put the cursor, false
276 if the index is unavailable */
277 bool
278 btr_cur_open_at_rnd_pos_func(
279 /*=========================*/
280 	dict_index_t*	index,		/*!< in: index */
281 	ulint		latch_mode,	/*!< in: BTR_SEARCH_LEAF, ... */
282 	btr_cur_t*	cursor,		/*!< in/out: B-tree cursor */
283 	const char*	file,		/*!< in: file name */
284 	ulint		line,		/*!< in: line where called */
285 	mtr_t*		mtr);		/*!< in: mtr */
286 #define btr_cur_open_at_rnd_pos(i,l,c,m)				\
287 	btr_cur_open_at_rnd_pos_func(i,l,c,__FILE__,__LINE__,m)
288 /*************************************************************//**
289 Tries to perform an insert to a page in an index tree, next to cursor.
290 It is assumed that mtr holds an x-latch on the page. The operation does
291 not succeed if there is too little space on the page. If there is just
292 one record on the page, the insert will always succeed; this is to
293 prevent trying to split a page with just one record.
294 @return DB_SUCCESS, DB_WAIT_LOCK, DB_FAIL, or error number */
295 dberr_t
296 btr_cur_optimistic_insert(
297 /*======================*/
298 	ulint		flags,	/*!< in: undo logging and locking flags: if not
299 				zero, the parameters index and thr should be
300 				specified */
301 	btr_cur_t*	cursor,	/*!< in: cursor on page after which to insert;
302 				cursor stays valid */
303 	ulint**		offsets,/*!< out: offsets on *rec */
304 	mem_heap_t**	heap,	/*!< in/out: pointer to memory heap, or NULL */
305 	dtuple_t*	entry,	/*!< in/out: entry to insert */
306 	rec_t**		rec,	/*!< out: pointer to inserted record if
307 				succeed */
308 	big_rec_t**	big_rec,/*!< out: big rec vector whose fields have to
309 				be stored externally by the caller, or
310 				NULL */
311 	ulint		n_ext,	/*!< in: number of externally stored columns */
312 	que_thr_t*	thr,	/*!< in: query thread or NULL */
313 	mtr_t*		mtr)	/*!< in/out: mini-transaction;
314 				if this function returns DB_SUCCESS on
315 				a leaf page of a secondary index in a
316 				compressed tablespace, the caller must
317 				mtr_commit(mtr) before latching
318 				any further pages */
319 	MY_ATTRIBUTE((warn_unused_result));
320 /*************************************************************//**
321 Performs an insert on a page of an index tree. It is assumed that mtr
322 holds an x-latch on the tree and on the cursor page. If the insert is
323 made on the leaf level, to avoid deadlocks, mtr must also own x-latches
324 to brothers of page, if those brothers exist.
325 @return DB_SUCCESS or error number */
326 dberr_t
327 btr_cur_pessimistic_insert(
328 /*=======================*/
329 	ulint		flags,	/*!< in: undo logging and locking flags: if not
330 				zero, the parameter thr should be
331 				specified; if no undo logging is specified,
332 				then the caller must have reserved enough
333 				free extents in the file space so that the
334 				insertion will certainly succeed */
335 	btr_cur_t*	cursor,	/*!< in: cursor after which to insert;
336 				cursor stays valid */
337 	ulint**		offsets,/*!< out: offsets on *rec */
338 	mem_heap_t**	heap,	/*!< in/out: pointer to memory heap
339 				that can be emptied, or NULL */
340 	dtuple_t*	entry,	/*!< in/out: entry to insert */
341 	rec_t**		rec,	/*!< out: pointer to inserted record if
342 				succeed */
343 	big_rec_t**	big_rec,/*!< out: big rec vector whose fields have to
344 				be stored externally by the caller, or
345 				NULL */
346 	ulint		n_ext,	/*!< in: number of externally stored columns */
347 	que_thr_t*	thr,	/*!< in: query thread or NULL */
348 	mtr_t*		mtr)	/*!< in/out: mini-transaction */
349 	MY_ATTRIBUTE((warn_unused_result));
350 /*************************************************************//**
351 See if there is enough place in the page modification log to log
352 an update-in-place.
353 
354 @retval false if out of space; IBUF_BITMAP_FREE will be reset
355 outside mtr if the page was recompressed
356 @retval true if enough place;
357 
358 IMPORTANT: The caller will have to update IBUF_BITMAP_FREE if this is
359 a secondary index leaf page. This has to be done either within the
360 same mini-transaction, or by invoking ibuf_reset_free_bits() before
361 mtr_commit(mtr). */
362 bool
363 btr_cur_update_alloc_zip_func(
364 /*==========================*/
365 	page_zip_des_t*	page_zip,/*!< in/out: compressed page */
366 	page_cur_t*	cursor,	/*!< in/out: B-tree page cursor */
367 	dict_index_t*	index,	/*!< in: the index corresponding to cursor */
368 #ifdef UNIV_DEBUG
369 	ulint*		offsets,/*!< in/out: offsets of the cursor record */
370 #endif /* UNIV_DEBUG */
371 	ulint		length,	/*!< in: size needed */
372 	bool		create,	/*!< in: true=delete-and-insert,
373 				false=update-in-place */
374 	mtr_t*		mtr)	/*!< in/out: mini-transaction */
375 	MY_ATTRIBUTE((warn_unused_result));
376 #ifdef UNIV_DEBUG
377 # define btr_cur_update_alloc_zip(page_zip,cursor,index,offsets,len,cr,mtr) \
378 	btr_cur_update_alloc_zip_func(page_zip,cursor,index,offsets,len,cr,mtr)
379 #else /* UNIV_DEBUG */
380 # define btr_cur_update_alloc_zip(page_zip,cursor,index,offsets,len,cr,mtr) \
381 	btr_cur_update_alloc_zip_func(page_zip,cursor,index,len,cr,mtr)
382 #endif /* UNIV_DEBUG */
383 /*************************************************************//**
384 Updates a record when the update causes no size changes in its fields.
385 @return locking or undo log related error code, or
386 @retval DB_SUCCESS on success
387 @retval DB_ZIP_OVERFLOW if there is not enough space left
388 on the compressed page (IBUF_BITMAP_FREE was reset outside mtr) */
389 dberr_t
390 btr_cur_update_in_place(
391 /*====================*/
392 	ulint		flags,	/*!< in: undo logging and locking flags */
393 	btr_cur_t*	cursor,	/*!< in: cursor on the record to update;
394 				cursor stays valid and positioned on the
395 				same record */
396 	ulint*		offsets,/*!< in/out: offsets on cursor->page_cur.rec */
397 	const upd_t*	update,	/*!< in: update vector */
398 	ulint		cmpl_info,/*!< in: compiler info on secondary index
399 				updates */
400 	que_thr_t*	thr,	/*!< in: query thread */
401 	trx_id_t	trx_id,	/*!< in: transaction id */
402 	mtr_t*		mtr)	/*!< in/out: mini-transaction; if this
403 				is a secondary index, the caller must
404 				mtr_commit(mtr) before latching any
405 				further pages */
406 	MY_ATTRIBUTE((warn_unused_result));
407 /***********************************************************//**
408 Writes a redo log record of updating a record in-place. */
409 void
410 btr_cur_update_in_place_log(
411 /*========================*/
412 	ulint		flags,		/*!< in: flags */
413 	const rec_t*	rec,		/*!< in: record */
414 	dict_index_t*	index,		/*!< in: index of the record */
415 	const upd_t*	update,		/*!< in: update vector */
416 	trx_id_t	trx_id,		/*!< in: transaction id */
417 	roll_ptr_t	roll_ptr,	/*!< in: roll ptr */
418 	mtr_t*		mtr);		/*!< in: mtr */
419 /*************************************************************//**
420 Tries to update a record on a page in an index tree. It is assumed that mtr
421 holds an x-latch on the page. The operation does not succeed if there is too
422 little space on the page or if the update would result in too empty a page,
423 so that tree compression is recommended.
424 @return error code, including
425 @retval DB_SUCCESS on success
426 @retval DB_OVERFLOW if the updated record does not fit
427 @retval DB_UNDERFLOW if the page would become too empty
428 @retval DB_ZIP_OVERFLOW if there is not enough space left
429 on the compressed page */
430 dberr_t
431 btr_cur_optimistic_update(
432 /*======================*/
433 	ulint		flags,	/*!< in: undo logging and locking flags */
434 	btr_cur_t*	cursor,	/*!< in: cursor on the record to update;
435 				cursor stays valid and positioned on the
436 				same record */
437 	ulint**		offsets,/*!< out: offsets on cursor->page_cur.rec */
438 	mem_heap_t**	heap,	/*!< in/out: pointer to NULL or memory heap */
439 	const upd_t*	update,	/*!< in: update vector; this must also
440 				contain trx id and roll ptr fields */
441 	ulint		cmpl_info,/*!< in: compiler info on secondary index
442 				updates */
443 	que_thr_t*	thr,	/*!< in: query thread */
444 	trx_id_t	trx_id,	/*!< in: transaction id */
445 	mtr_t*		mtr)	/*!< in/out: mini-transaction; if this
446 				is a secondary index, the caller must
447 				mtr_commit(mtr) before latching any
448 				further pages */
449 	MY_ATTRIBUTE((warn_unused_result));
450 /*************************************************************//**
451 Performs an update of a record on a page of a tree. It is assumed
452 that mtr holds an x-latch on the tree and on the cursor page. If the
453 update is made on the leaf level, to avoid deadlocks, mtr must also
454 own x-latches to brothers of page, if those brothers exist.
455 @return DB_SUCCESS or error code */
456 dberr_t
457 btr_cur_pessimistic_update(
458 /*=======================*/
459 	ulint		flags,	/*!< in: undo logging, locking, and rollback
460 				flags */
461 	btr_cur_t*	cursor,	/*!< in/out: cursor on the record to update;
462 				cursor may become invalid if *big_rec == NULL
463 				|| !(flags & BTR_KEEP_POS_FLAG) */
464 	ulint**		offsets,/*!< out: offsets on cursor->page_cur.rec */
465 	mem_heap_t**	offsets_heap,
466 				/*!< in/out: pointer to memory heap
467 				that can be emptied, or NULL */
468 	mem_heap_t*	entry_heap,
469 				/*!< in/out: memory heap for allocating
470 				big_rec and the index tuple */
471 	big_rec_t**	big_rec,/*!< out: big rec vector whose fields have to
472 				be stored externally by the caller, or NULL */
473 	upd_t*		update,	/*!< in/out: update vector; this is allowed to
474 				also contain trx id and roll ptr fields.
475 				Non-updated columns that are moved offpage will
476 				be appended to this. */
477 	ulint		cmpl_info,/*!< in: compiler info on secondary index
478 				updates */
479 	que_thr_t*	thr,	/*!< in: query thread */
480 	trx_id_t	trx_id,	/*!< in: transaction id */
481 	mtr_t*		mtr)	/*!< in/out: mini-transaction; must be committed
482 				before latching any further pages */
483 	MY_ATTRIBUTE((warn_unused_result));
484 /***********************************************************//**
485 Marks a clustered index record deleted. Writes an undo log record to
486 undo log on this delete marking. Writes in the trx id field the id
487 of the deleting transaction, and in the roll ptr field pointer to the
488 undo log record created.
489 @return DB_SUCCESS, DB_LOCK_WAIT, or error number */
490 dberr_t
491 btr_cur_del_mark_set_clust_rec(
492 /*===========================*/
493 	ulint		flags,  /*!< in: undo logging and locking flags */
494 	buf_block_t*	block,	/*!< in/out: buffer block of the record */
495 	rec_t*		rec,	/*!< in/out: record */
496 	dict_index_t*	index,	/*!< in: clustered index of the record */
497 	const ulint*	offsets,/*!< in: rec_get_offsets(rec) */
498 	que_thr_t*	thr,	/*!< in: query thread */
499 	const dtuple_t*	entry,	/*!< in: dtuple for the deleting record */
500 	mtr_t*		mtr)	/*!< in/out: mini-transaction */
501 	MY_ATTRIBUTE((warn_unused_result));
502 /***********************************************************//**
503 Sets a secondary index record delete mark to TRUE or FALSE.
504 @return DB_SUCCESS, DB_LOCK_WAIT, or error number */
505 dberr_t
506 btr_cur_del_mark_set_sec_rec(
507 /*=========================*/
508 	ulint		flags,	/*!< in: locking flag */
509 	btr_cur_t*	cursor,	/*!< in: cursor */
510 	ibool		val,	/*!< in: value to set */
511 	que_thr_t*	thr,	/*!< in: query thread */
512 	mtr_t*		mtr)	/*!< in/out: mini-transaction */
513 	MY_ATTRIBUTE((warn_unused_result));
514 /*************************************************************//**
515 Tries to compress a page of the tree if it seems useful. It is assumed
516 that mtr holds an x-latch on the tree and on the cursor page. To avoid
517 deadlocks, mtr must also own x-latches to brothers of page, if those
518 brothers exist. NOTE: it is assumed that the caller has reserved enough
519 free extents so that the compression will always succeed if done!
520 @return TRUE if compression occurred */
521 ibool
522 btr_cur_compress_if_useful(
523 /*=======================*/
524 	btr_cur_t*	cursor,	/*!< in/out: cursor on the page to compress;
525 				cursor does not stay valid if compression
526 				occurs */
527 	ibool		adjust,	/*!< in: TRUE if should adjust the
528 				cursor position even if compression occurs */
529 	mtr_t*		mtr);	/*!< in/out: mini-transaction */
530 /*******************************************************//**
531 Removes the record on which the tree cursor is positioned. It is assumed
532 that the mtr has an x-latch on the page where the cursor is positioned,
533 but no latch on the whole tree.
534 @return TRUE if success, i.e., the page did not become too empty */
535 ibool
536 btr_cur_optimistic_delete_func(
537 /*===========================*/
538 	btr_cur_t*	cursor,	/*!< in: cursor on the record to delete;
539 				cursor stays valid: if deletion succeeds,
540 				on function exit it points to the successor
541 				of the deleted record */
542 # ifdef UNIV_DEBUG
543 	ulint		flags,	/*!< in: BTR_CREATE_FLAG or 0 */
544 # endif /* UNIV_DEBUG */
545 	mtr_t*		mtr)	/*!< in: mtr; if this function returns
546 				TRUE on a leaf page of a secondary
547 				index, the mtr must be committed
548 				before latching any further pages */
549 	MY_ATTRIBUTE((warn_unused_result));
550 # ifdef UNIV_DEBUG
551 #  define btr_cur_optimistic_delete(cursor, flags, mtr)		\
552 	btr_cur_optimistic_delete_func(cursor, flags, mtr)
553 # else /* UNIV_DEBUG */
554 #  define btr_cur_optimistic_delete(cursor, flags, mtr)		\
555 	btr_cur_optimistic_delete_func(cursor, mtr)
556 # endif /* UNIV_DEBUG */
557 /*************************************************************//**
558 Removes the record on which the tree cursor is positioned. Tries
559 to compress the page if its fillfactor drops below a threshold
560 or if it is the only page on the level. It is assumed that mtr holds
561 an x-latch on the tree and on the cursor page. To avoid deadlocks,
562 mtr must also own x-latches to brothers of page, if those brothers
563 exist.
564 @return TRUE if compression occurred */
565 ibool
566 btr_cur_pessimistic_delete(
567 /*=======================*/
568 	dberr_t*		err,	/*!< out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE;
569 				the latter may occur because we may have
570 				to update node pointers on upper levels,
571 				and in the case of variable length keys
572 				these may actually grow in size */
573 	ibool		has_reserved_extents, /*!< in: TRUE if the
574 				caller has already reserved enough free
575 				extents so that he knows that the operation
576 				will succeed */
577 	btr_cur_t*	cursor,	/*!< in: cursor on the record to delete;
578 				if compression does not occur, the cursor
579 				stays valid: it points to successor of
580 				deleted record on function exit */
581 	ulint		flags,	/*!< in: BTR_CREATE_FLAG or 0 */
582 	bool		rollback,/*!< in: performing rollback? */
583 	mtr_t*		mtr);	/*!< in: mtr */
584 #endif /* !UNIV_HOTBACKUP */
585 /***********************************************************//**
586 Parses a redo log record of updating a record in-place.
587 @return end of log record or NULL */
588 byte*
589 btr_cur_parse_update_in_place(
590 /*==========================*/
591 	byte*		ptr,	/*!< in: buffer */
592 	byte*		end_ptr,/*!< in: buffer end */
593 	page_t*		page,	/*!< in/out: page or NULL */
594 	page_zip_des_t*	page_zip,/*!< in/out: compressed page, or NULL */
595 	dict_index_t*	index);	/*!< in: index corresponding to page */
596 /****************************************************************//**
597 Parses the redo log record for delete marking or unmarking of a clustered
598 index record.
599 @return end of log record or NULL */
600 byte*
601 btr_cur_parse_del_mark_set_clust_rec(
602 /*=================================*/
603 	byte*		ptr,	/*!< in: buffer */
604 	byte*		end_ptr,/*!< in: buffer end */
605 	page_t*		page,	/*!< in/out: page or NULL */
606 	page_zip_des_t*	page_zip,/*!< in/out: compressed page, or NULL */
607 	dict_index_t*	index);	/*!< in: index corresponding to page */
608 /****************************************************************//**
609 Parses the redo log record for delete marking or unmarking of a secondary
610 index record.
611 @return end of log record or NULL */
612 byte*
613 btr_cur_parse_del_mark_set_sec_rec(
614 /*===============================*/
615 	byte*		ptr,	/*!< in: buffer */
616 	byte*		end_ptr,/*!< in: buffer end */
617 	page_t*		page,	/*!< in/out: page or NULL */
618 	page_zip_des_t*	page_zip);/*!< in/out: compressed page, or NULL */
619 #ifndef UNIV_HOTBACKUP
620 
621 /** Estimates the number of rows in a given index range.
622 @param[in]	index	index
623 @param[in]	tuple1	range start, may also be empty tuple
624 @param[in]	mode1	search mode for range start
625 @param[in]	tuple2	range end, may also be empty tuple
626 @param[in]	mode2	search mode for range end
627 @return estimated number of rows */
628 int64_t
629 btr_estimate_n_rows_in_range(
630 	dict_index_t*	index,
631 	const dtuple_t*	tuple1,
632 	page_cur_mode_t	mode1,
633 	const dtuple_t*	tuple2,
634 	page_cur_mode_t	mode2);
635 
636 /*******************************************************************//**
637 Estimates the number of different key values in a given index, for
638 each n-column prefix of the index where 1 <= n <= dict_index_get_n_unique(index).
639 The estimates are stored in the array index->stat_n_diff_key_vals[] (indexed
640 0..n_uniq-1) and the number of pages that were sampled is saved in
641 index->stat_n_sample_sizes[].
642 If innodb_stats_method is nulls_ignored, we also record the number of
643 non-null values for each prefix and stored the estimates in
644 array index->stat_n_non_null_key_vals.
645 @return true if the index is available and we get the estimated numbers,
646 false if the index is unavailable. */
647 bool
648 btr_estimate_number_of_different_key_vals(
649 /*======================================*/
650 	dict_index_t*	index);	/*!< in: index */
651 
652 /** Gets the externally stored size of a record, in units of a database page.
653 @param[in]	rec	record
654 @param[in]	offsets	array returned by rec_get_offsets()
655 @return externally stored part, in units of a database page */
656 ulint
657 btr_rec_get_externally_stored_len(
658 	const rec_t*	rec,
659 	const ulint*	offsets);
660 
661 /*******************************************************************//**
662 Marks non-updated off-page fields as disowned by this record. The ownership
663 must be transferred to the updated record which is inserted elsewhere in the
664 index tree. In purge only the owner of externally stored field is allowed
665 to free the field. */
666 void
667 btr_cur_disown_inherited_fields(
668 /*============================*/
669 	page_zip_des_t*	page_zip,/*!< in/out: compressed page whose uncompressed
670 				part will be updated, or NULL */
671 	rec_t*		rec,	/*!< in/out: record in a clustered index */
672 	dict_index_t*	index,	/*!< in: index of the page */
673 	const ulint*	offsets,/*!< in: array returned by rec_get_offsets() */
674 	const upd_t*	update,	/*!< in: update vector */
675 	mtr_t*		mtr);	/*!< in/out: mini-transaction */
676 
677 /** Operation code for btr_store_big_rec_extern_fields(). */
678 enum blob_op {
679 	/** Store off-page columns for a freshly inserted record */
680 	BTR_STORE_INSERT = 0,
681 	/** Store off-page columns for an insert by update */
682 	BTR_STORE_INSERT_UPDATE,
683 	/** Store off-page columns for an update */
684 	BTR_STORE_UPDATE,
685 	/** Store off-page columns for a freshly inserted record by bulk */
686 	BTR_STORE_INSERT_BULK
687 };
688 
689 /*******************************************************************//**
690 Determine if an operation on off-page columns is an update.
691 @return TRUE if op != BTR_STORE_INSERT */
692 UNIV_INLINE
693 ibool
694 btr_blob_op_is_update(
695 /*==================*/
696 	enum blob_op	op)	/*!< in: operation */
697 	MY_ATTRIBUTE((warn_unused_result));
698 
699 /*******************************************************************//**
700 Stores the fields in big_rec_vec to the tablespace and puts pointers to
701 them in rec.  The extern flags in rec will have to be set beforehand.
702 The fields are stored on pages allocated from leaf node
703 file segment of the index tree.
704 @return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
705 dberr_t
706 btr_store_big_rec_extern_fields(
707 /*============================*/
708 	btr_pcur_t*	pcur,		/*!< in/out: a persistent cursor. if
709 					btr_mtr is restarted, then this can
710 					be repositioned. */
711 	const upd_t*	upd,		/*!< in: update vector */
712 	ulint*		offsets,	/*!< in/out: rec_get_offsets() on
713 					pcur. the "external storage" flags
714 					in offsets will correctly correspond
715 					to rec when this function returns */
716 	const big_rec_t*big_rec_vec,	/*!< in: vector containing fields
717 					to be stored externally */
718 	mtr_t*		btr_mtr,	/*!< in/out: mtr containing the
719 					latches to the clustered index. can be
720 					committed and restarted. */
721 	enum blob_op	op)		/*! in: operation code */
722 	MY_ATTRIBUTE((warn_unused_result));
723 
724 /*******************************************************************//**
725 Frees the space in an externally stored field to the file space
726 management if the field in data is owned the externally stored field,
727 in a rollback we may have the additional condition that the field must
728 not be inherited. */
729 void
730 btr_free_externally_stored_field(
731 /*=============================*/
732 	dict_index_t*	index,		/*!< in: index of the data, the index
733 					tree MUST be X-latched; if the tree
734 					height is 1, then also the root page
735 					must be X-latched! (this is relevant
736 					in the case this function is called
737 					from purge where 'data' is located on
738 					an undo log page, not an index
739 					page) */
740 	byte*		field_ref,	/*!< in/out: field reference */
741 	const rec_t*	rec,		/*!< in: record containing field_ref, for
742 					page_zip_write_blob_ptr(), or NULL */
743 	const ulint*	offsets,	/*!< in: rec_get_offsets(rec, index),
744 					or NULL */
745 	page_zip_des_t*	page_zip,	/*!< in: compressed page corresponding
746 					to rec, or NULL if rec == NULL */
747 	ulint		i,		/*!< in: field number of field_ref;
748 					ignored if rec == NULL */
749 	bool		rollback,	/*!< in: performing rollback? */
750 	mtr_t*		local_mtr);	/*!< in: mtr containing the latch */
751 /** Copies the prefix of an externally stored field of a record.
752 The clustered index record must be protected by a lock or a page latch.
753 @param[out]	buf		the field, or a prefix of it
754 @param[in]	len		length of buf, in bytes
755 @param[in]	page_size	BLOB page size
756 @param[in]	data		'internally' stored part of the field
757 containing also the reference to the external part; must be protected by
758 a lock or a page latch
759 @param[in]	local_len	length of data, in bytes
760 @return the length of the copied field, or 0 if the column was being
761 or has been deleted */
762 ulint
763 btr_copy_externally_stored_field_prefix(
764 	byte*			buf,
765 	ulint			len,
766 	const page_size_t&	page_size,
767 	const byte*		data,
768 	ulint			local_len);
769 
770 /** Copies an externally stored field of a record to mem heap.
771 The clustered index record must be protected by a lock or a page latch.
772 @param[out]	len		length of the whole field
773 @param[in]	data		'internally' stored part of the field
774 containing also the reference to the external part; must be protected by
775 a lock or a page latch
776 @param[in]	page_size	BLOB page size
777 @param[in]	local_len	length of data
778 @param[in,out]	heap		mem heap
779 @return the whole field copied to heap */
780 byte*
781 btr_copy_externally_stored_field(
782 	ulint*			len,
783 	const byte*		data,
784 	const page_size_t&	page_size,
785 	ulint			local_len,
786 	mem_heap_t*		heap);
787 
788 /** Copies an externally stored field of a record to mem heap.
789 @param[in]	rec		record in a clustered index; must be
790 protected by a lock or a page latch
791 @param[in]	offset		array returned by rec_get_offsets()
792 @param[in]	page_size	BLOB page size
793 @param[in]	no		field number
794 @param[out]	len		length of the field
795 @param[in,out]	heap		mem heap
796 @return the field copied to heap, or NULL if the field is incomplete */
797 byte*
798 btr_rec_copy_externally_stored_field(
799 	const rec_t*		rec,
800 	const ulint*		offsets,
801 	const page_size_t&	page_size,
802 	ulint			no,
803 	ulint*			len,
804 	mem_heap_t*		heap);
805 
806 /***********************************************************//**
807 Sets a secondary index record's delete mark to the given value. This
808 function is only used by the insert buffer merge mechanism. */
809 void
810 btr_cur_set_deleted_flag_for_ibuf(
811 /*==============================*/
812 	rec_t*		rec,		/*!< in/out: record */
813 	page_zip_des_t*	page_zip,	/*!< in/out: compressed page
814 					corresponding to rec, or NULL
815 					when the tablespace is uncompressed */
816 	ibool		val,		/*!< in: value to set */
817 	mtr_t*		mtr);		/*!< in/out: mini-transaction */
818 
819 /******************************************************//**
820 The following function is used to set the deleted bit of a record. */
821 UNIV_INLINE
822 void
823 btr_rec_set_deleted_flag(
824 /*=====================*/
825 	rec_t*		rec,	/*!< in/out: physical record */
826 	page_zip_des_t*	page_zip,/*!< in/out: compressed page (or NULL) */
827 	ulint		flag);	/*!< in: nonzero if delete marked */
828 
829 /** Latches the leaf page or pages requested.
830 @param[in]	block		leaf page where the search converged
831 @param[in]	page_id		page id of the leaf
832 @param[in]	latch_mode	BTR_SEARCH_LEAF, ...
833 @param[in]	cursor		cursor
834 @param[in]	mtr		mini-transaction
835 @return	blocks and savepoints which actually latched. */
836 btr_latch_leaves_t
837 btr_cur_latch_leaves(
838 	buf_block_t*		block,
839 	const page_id_t&	page_id,
840 	const page_size_t&	page_size,
841 	ulint			latch_mode,
842 	btr_cur_t*		cursor,
843 	mtr_t*			mtr);
844 
845 /*######################################################################*/
846 
847 /** In the pessimistic delete, if the page data size drops below this
848 limit, merging it to a neighbor is tried */
849 #define BTR_CUR_PAGE_COMPRESS_LIMIT(index) \
850 	((UNIV_PAGE_SIZE * (ulint)((index)->merge_threshold)) / 100)
851 
852 /** A slot in the path array. We store here info on a search path down the
853 tree. Each slot contains data on a single level of the tree. */
854 struct btr_path_t {
855 	/* Assume a page like:
856 	records:             (inf, a, b, c, d, sup)
857 	index of the record:    0, 1, 2, 3, 4, 5
858 	*/
859 
860 	/** Index of the record where the page cursor stopped on this level
861 	(index in alphabetical order). Value ULINT_UNDEFINED denotes array
862 	end. In the above example, if the search stopped on record 'c', then
863 	nth_rec will be 3. */
864 	ulint	nth_rec;
865 
866 	/** Number of the records on the page, not counting inf and sup.
867 	In the above example n_recs will be 4. */
868 	ulint	n_recs;
869 
870 	/** Number of the page containing the record. */
871 	ulint	page_no;
872 
873 	/** Level of the page. If later we fetch the page under page_no
874 	and it is no different level then we know that the tree has been
875 	reorganized. */
876 	ulint	page_level;
877 };
878 
879 #define BTR_PATH_ARRAY_N_SLOTS	250	/*!< size of path array (in slots) */
880 
881 /** Values for the flag documenting the used search method */
882 enum btr_cur_method {
883 	BTR_CUR_HASH = 1,	/*!< successful shortcut using
884 				the hash index */
885 	BTR_CUR_HASH_FAIL,	/*!< failure using hash, success using
886 				binary search: the misleading hash
887 				reference is stored in the field
888 				hash_node, and might be necessary to
889 				update */
890 	BTR_CUR_BINARY,		/*!< success using the binary search */
891 	BTR_CUR_INSERT_TO_IBUF,	/*!< performed the intended insert to
892 				the insert buffer */
893 	BTR_CUR_DEL_MARK_IBUF,	/*!< performed the intended delete
894 				mark in the insert/delete buffer */
895 	BTR_CUR_DELETE_IBUF,	/*!< performed the intended delete in
896 				the insert/delete buffer */
897 	BTR_CUR_DELETE_REF	/*!< row_purge_poss_sec() failed */
898 };
899 
900 /** The tree cursor: the definition appears here only for the compiler
901 to know struct size! */
902 struct btr_cur_t {
btr_cur_tbtr_cur_t903 	btr_cur_t() { memset(this, 0, sizeof(*this)); }
904 
905 	dict_index_t*	index;		/*!< index where positioned */
906 	page_cur_t	page_cur;	/*!< page cursor */
907 	purge_node_t*	purge_node;	/*!< purge node, for BTR_DELETE */
908 	buf_block_t*	left_block;	/*!< this field is used to store
909 					a pointer to the left neighbor
910 					page, in the cases
911 					BTR_SEARCH_PREV and
912 					BTR_MODIFY_PREV */
913 	/*------------------------------*/
914 	que_thr_t*	thr;		/*!< this field is only used
915 					when btr_cur_search_to_nth_level
916 					is called for an index entry
917 					insertion: the calling query
918 					thread is passed here to be
919 					used in the insert buffer */
920 	/*------------------------------*/
921 	/** The following fields are used in
922 	btr_cur_search_to_nth_level to pass information: */
923 	/* @{ */
924 	enum btr_cur_method	flag;	/*!< Search method used */
925 	ulint		tree_height;	/*!< Tree height if the search is done
926 					for a pessimistic insert or update
927 					operation */
928 	ulint		up_match;	/*!< If the search mode was PAGE_CUR_LE,
929 					the number of matched fields to the
930 					the first user record to the right of
931 					the cursor record after
932 					btr_cur_search_to_nth_level;
933 					for the mode PAGE_CUR_GE, the matched
934 					fields to the first user record AT THE
935 					CURSOR or to the right of it;
936 					NOTE that the up_match and low_match
937 					values may exceed the correct values
938 					for comparison to the adjacent user
939 					record if that record is on a
940 					different leaf page! (See the note in
941 					row_ins_duplicate_error_in_clust.) */
942 	ulint		up_bytes;	/*!< number of matched bytes to the
943 					right at the time cursor positioned;
944 					only used internally in searches: not
945 					defined after the search */
946 	ulint		low_match;	/*!< if search mode was PAGE_CUR_LE,
947 					the number of matched fields to the
948 					first user record AT THE CURSOR or
949 					to the left of it after
950 					btr_cur_search_to_nth_level;
951 					NOT defined for PAGE_CUR_GE or any
952 					other search modes; see also the NOTE
953 					in up_match! */
954 	ulint		low_bytes;	/*!< number of matched bytes to the
955 					left at the time cursor positioned;
956 					only used internally in searches: not
957 					defined after the search */
958 	ulint		n_fields;	/*!< prefix length used in a hash
959 					search if hash_node != NULL */
960 	ulint		n_bytes;	/*!< hash prefix bytes if hash_node !=
961 					NULL */
962 	ulint		fold;		/*!< fold value used in the search if
963 					flag is BTR_CUR_HASH */
964 	/* @} */
965 	btr_path_t*	path_arr;	/*!< in estimating the number of
966 					rows in range, we store in this array
967 					information of the path through
968 					the tree */
969 	rtr_info_t*	rtr_info;	/*!< rtree search info */
970 					/* default values */
971 };
972 
973 /******************************************************//**
974 The following function is used to set the deleted bit of a record. */
975 UNIV_INLINE
976 void
977 btr_rec_set_deleted_flag(
978 /*=====================*/
979 	rec_t*		rec,	/*!< in/out: physical record */
980 	page_zip_des_t*	page_zip,/*!< in/out: compressed page (or NULL) */
981 	ulint		flag);	/*!< in: nonzero if delete marked */
982 
983 
984 /** If pessimistic delete fails because of lack of file space, there
985 is still a good change of success a little later.  Try this many
986 times. */
987 #define BTR_CUR_RETRY_DELETE_N_TIMES	100
988 /** If pessimistic delete fails because of lack of file space, there
989 is still a good change of success a little later.  Sleep this many
990 microseconds between retries. */
991 #define BTR_CUR_RETRY_SLEEP_TIME	50000
992 
993 /** The reference in a field for which data is stored on a different page.
994 The reference is at the end of the 'locally' stored part of the field.
995 'Locally' means storage in the index record.
996 We store locally a long enough prefix of each column so that we can determine
997 the ordering parts of each index record without looking into the externally
998 stored part. */
999 /*-------------------------------------- @{ */
1000 #define BTR_EXTERN_SPACE_ID		0	/*!< space id where stored */
1001 #define BTR_EXTERN_PAGE_NO		4	/*!< page no where stored */
1002 #define BTR_EXTERN_OFFSET		8	/*!< offset of BLOB header
1003 						on that page */
1004 #define BTR_EXTERN_LEN			12	/*!< 8 bytes containing the
1005 						length of the externally
1006 						stored part of the BLOB.
1007 						The 2 highest bits are
1008 						reserved to the flags below. */
1009 /*-------------------------------------- @} */
1010 /* #define BTR_EXTERN_FIELD_REF_SIZE	20 // moved to btr0types.h */
1011 
1012 /** The most significant bit of BTR_EXTERN_LEN (i.e., the most
1013 significant bit of the byte at smallest address) is set to 1 if this
1014 field does not 'own' the externally stored field; only the owner field
1015 is allowed to free the field in purge! */
1016 #define BTR_EXTERN_OWNER_FLAG		128
1017 /** If the second most significant bit of BTR_EXTERN_LEN (i.e., the
1018 second most significant bit of the byte at smallest address) is 1 then
1019 it means that the externally stored field was inherited from an
1020 earlier version of the row.  In rollback we are not allowed to free an
1021 inherited external field. */
1022 #define BTR_EXTERN_INHERITED_FLAG	64
1023 
1024 /** Number of searches down the B-tree in btr_cur_search_to_nth_level(). */
1025 extern ulint	btr_cur_n_non_sea;
1026 /** Number of successful adaptive hash index lookups in
1027 btr_cur_search_to_nth_level(). */
1028 extern ulint	btr_cur_n_sea;
1029 /** Old value of btr_cur_n_non_sea.  Copied by
1030 srv_refresh_innodb_monitor_stats().  Referenced by
1031 srv_printf_innodb_monitor(). */
1032 extern ulint	btr_cur_n_non_sea_old;
1033 /** Old value of btr_cur_n_sea.  Copied by
1034 srv_refresh_innodb_monitor_stats().  Referenced by
1035 srv_printf_innodb_monitor(). */
1036 extern ulint	btr_cur_n_sea_old;
1037 #endif /* !UNIV_HOTBACKUP */
1038 
1039 #ifdef UNIV_DEBUG
1040 /* Flag to limit optimistic insert records */
1041 extern uint	btr_cur_limit_optimistic_insert_debug;
1042 #endif /* UNIV_DEBUG */
1043 
1044 #ifndef UNIV_NONINL
1045 #include "btr0cur.ic"
1046 #endif
1047 
1048 #endif
1049