1 /*****************************************************************************
2 
3 Copyright (c) 1996, 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/btr0pcur.h
29 The index tree persistent cursor
30 
31 Created 2/23/1996 Heikki Tuuri
32 *******************************************************/
33 
34 #ifndef btr0pcur_h
35 #define btr0pcur_h
36 
37 #include "univ.i"
38 #include "dict0dict.h"
39 #include "data0data.h"
40 #include "mtr0mtr.h"
41 #include "page0cur.h"
42 #include "btr0cur.h"
43 #include "btr0btr.h"
44 #include "buf0block_hint.h"
45 #include "btr0types.h"
46 #include "gis0rtree.h"
47 
48 /* Relative positions for a stored cursor position */
49 enum btr_pcur_pos_t {
50 	BTR_PCUR_ON		= 1,
51 	BTR_PCUR_BEFORE		= 2,
52 	BTR_PCUR_AFTER		= 3,
53 /* Note that if the tree is not empty, btr_pcur_store_position does not
54 use the following, but only uses the above three alternatives, where the
55 position is stored relative to a specific record: this makes implementation
56 of a scroll cursor easier */
57 	BTR_PCUR_BEFORE_FIRST_IN_TREE	= 4,	/* in an empty tree */
58 	BTR_PCUR_AFTER_LAST_IN_TREE	= 5	/* in an empty tree */
59 };
60 
61 /**************************************************************//**
62 Allocates memory for a persistent cursor object and initializes the cursor.
63 @return own: persistent cursor */
64 btr_pcur_t*
65 btr_pcur_create_for_mysql(void);
66 /*============================*/
67 
68 /**************************************************************//**
69 Resets a persistent cursor object, freeing ::old_rec_buf if it is
70 allocated and resetting the other members to their initial values. */
71 void
72 btr_pcur_reset(
73 /*===========*/
74 	btr_pcur_t*	cursor);/*!< in, out: persistent cursor */
75 
76 /**************************************************************//**
77 Frees the memory for a persistent cursor object. */
78 void
79 btr_pcur_free_for_mysql(
80 /*====================*/
81 	btr_pcur_t*	cursor);	/*!< in, own: persistent cursor */
82 /**************************************************************//**
83 Copies the stored position of a pcur to another pcur. */
84 void
85 btr_pcur_copy_stored_position(
86 /*==========================*/
87 	btr_pcur_t*	pcur_receive,	/*!< in: pcur which will receive the
88 					position info */
89 	btr_pcur_t*	pcur_donate);	/*!< in: pcur from which the info is
90 					copied */
91 /**************************************************************//**
92 Sets the old_rec_buf field to NULL. */
93 UNIV_INLINE
94 void
95 btr_pcur_init(
96 /*==========*/
97 	btr_pcur_t*	pcur);	/*!< in: persistent cursor */
98 
99 /** Free old_rec_buf.
100 @param[in]	pcur	Persistent cursor holding old_rec to be freed. */
101 UNIV_INLINE
102 void
103 btr_pcur_free(
104 	btr_pcur_t*	pcur);
105 
106 /**************************************************************//**
107 Initializes and opens a persistent cursor to an index tree. It should be
108 closed with btr_pcur_close. */
109 UNIV_INLINE
110 dberr_t
111 btr_pcur_open_low(
112 /*==============*/
113 	dict_index_t*	index,	/*!< in: index */
114 	ulint		level,	/*!< in: level in the btree */
115 	const dtuple_t*	tuple,	/*!< in: tuple on which search done */
116 	page_cur_mode_t	mode,	/*!< in: PAGE_CUR_L, ...;
117 				NOTE that if the search is made using a unique
118 				prefix of a record, mode should be
119 				PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
120 				may end up on the previous page from the
121 				record! */
122 	ulint		latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */
123 	btr_pcur_t*	cursor, /*!< in: memory buffer for persistent cursor */
124 	const char*	file,	/*!< in: file name */
125 	ulint		line,	/*!< in: line where called */
126 	mtr_t*		mtr);	/*!< in: mtr */
127 #define btr_pcur_open(i,t,md,l,c,m)				\
128 	btr_pcur_open_low(i,0,t,md,l,c,__FILE__,__LINE__,m)
129 /**************************************************************//**
130 Opens an persistent cursor to an index tree without initializing the
131 cursor. */
132 UNIV_INLINE
133 dberr_t
134 btr_pcur_open_with_no_init_func(
135 /*============================*/
136 	dict_index_t*	index,	/*!< in: index */
137 	const dtuple_t*	tuple,	/*!< in: tuple on which search done */
138 	page_cur_mode_t	mode,	/*!< in: PAGE_CUR_L, ...;
139 				NOTE that if the search is made using a unique
140 				prefix of a record, mode should be
141 				PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
142 				may end up on the previous page of the
143 				record! */
144 	ulint		latch_mode,/*!< in: BTR_SEARCH_LEAF, ...;
145 				NOTE that if has_search_latch != 0 then
146 				we maybe do not acquire a latch on the cursor
147 				page, but assume that the caller uses his
148 				btr search latch to protect the record! */
149 	btr_pcur_t*	cursor, /*!< in: memory buffer for persistent cursor */
150 	ulint		has_search_latch,
151 				/*!< in: latch mode the caller
152 				currently has on search system:
153 				RW_S_LATCH, or 0 */
154 	const char*	file,	/*!< in: file name */
155 	ulint		line,	/*!< in: line where called */
156 	mtr_t*		mtr);	/*!< in: mtr */
157 #define btr_pcur_open_with_no_init(ix,t,md,l,cur,has,m)			\
158 	btr_pcur_open_with_no_init_func(ix,t,md,l,cur,has,__FILE__,__LINE__,m)
159 
160 /*****************************************************************//**
161 Opens a persistent cursor at either end of an index. */
162 UNIV_INLINE
163 dberr_t
164 btr_pcur_open_at_index_side(
165 /*========================*/
166 	bool		from_left,	/*!< in: true if open to the low end,
167 					false if to the high end */
168 	dict_index_t*	index,		/*!< in: index */
169 	ulint		latch_mode,	/*!< in: latch mode */
170 	btr_pcur_t*	pcur,		/*!< in/out: cursor */
171 	bool		init_pcur,	/*!< in: whether to initialize pcur */
172 	ulint		level,		/*!< in: level to search for
173 					(0=leaf) */
174 	mtr_t*		mtr)		/*!< in/out: mini-transaction */
175 	MY_ATTRIBUTE((nonnull));
176 /**************************************************************//**
177 Gets the up_match value for a pcur after a search.
178 @return number of matched fields at the cursor or to the right if
179 search mode was PAGE_CUR_GE, otherwise undefined */
180 UNIV_INLINE
181 ulint
182 btr_pcur_get_up_match(
183 /*==================*/
184 	const btr_pcur_t*	cursor); /*!< in: persistent cursor */
185 /**************************************************************//**
186 Gets the low_match value for a pcur after a search.
187 @return number of matched fields at the cursor or to the right if
188 search mode was PAGE_CUR_LE, otherwise undefined */
189 UNIV_INLINE
190 ulint
191 btr_pcur_get_low_match(
192 /*===================*/
193 	const btr_pcur_t*	cursor); /*!< in: persistent cursor */
194 /**************************************************************//**
195 If mode is PAGE_CUR_G or PAGE_CUR_GE, opens a persistent cursor on the first
196 user record satisfying the search condition, in the case PAGE_CUR_L or
197 PAGE_CUR_LE, on the last user record. If no such user record exists, then
198 in the first case sets the cursor after last in tree, and in the latter case
199 before first in tree. The latching mode must be BTR_SEARCH_LEAF or
200 BTR_MODIFY_LEAF. */
201 void
202 btr_pcur_open_on_user_rec_func(
203 /*===========================*/
204 	dict_index_t*	index,		/*!< in: index */
205 	const dtuple_t*	tuple,		/*!< in: tuple on which search done */
206 	page_cur_mode_t	mode,		/*!< in: PAGE_CUR_L, ... */
207 	ulint		latch_mode,	/*!< in: BTR_SEARCH_LEAF or
208 					BTR_MODIFY_LEAF */
209 	btr_pcur_t*	cursor,		/*!< in: memory buffer for persistent
210 					cursor */
211 	const char*	file,		/*!< in: file name */
212 	ulint		line,		/*!< in: line where called */
213 	mtr_t*		mtr);		/*!< in: mtr */
214 #define btr_pcur_open_on_user_rec(i,t,md,l,c,m)				\
215 	btr_pcur_open_on_user_rec_func(i,t,md,l,c,__FILE__,__LINE__,m)
216 /**********************************************************************//**
217 Positions a cursor at a randomly chosen position within a B-tree.
218 @return true if the index is available and we have put the cursor, false
219 if the index is unavailable */
220 UNIV_INLINE
221 bool
222 btr_pcur_open_at_rnd_pos_func(
223 /*==========================*/
224 	dict_index_t*	index,		/*!< in: index */
225 	ulint		latch_mode,	/*!< in: BTR_SEARCH_LEAF, ... */
226 	btr_pcur_t*	cursor,		/*!< in/out: B-tree pcur */
227 	const char*	file,		/*!< in: file name */
228 	ulint		line,		/*!< in: line where called */
229 	mtr_t*		mtr);		/*!< in: mtr */
230 #define btr_pcur_open_at_rnd_pos(i,l,c,m)				\
231 	btr_pcur_open_at_rnd_pos_func(i,l,c,__FILE__,__LINE__,m)
232 /**************************************************************//**
233 Frees the possible memory heap of a persistent cursor and sets the latch
234 mode of the persistent cursor to BTR_NO_LATCHES.
235 WARNING: this function does not release the latch on the page where the
236 cursor is currently positioned. The latch is acquired by the
237 "move to next/previous" family of functions. Since recursive shared locks
238 are not allowed, you must take care (if using the cursor in S-mode) to
239 manually release the latch by either calling
240 btr_leaf_page_release(btr_pcur_get_block(&pcur), pcur.latch_mode, mtr)
241 or by committing the mini-transaction right after btr_pcur_close().
242 A subsequent attempt to crawl the same page in the same mtr would cause
243 an assertion failure. */
244 UNIV_INLINE
245 void
246 btr_pcur_close(
247 /*===========*/
248 	btr_pcur_t*	cursor);	/*!< in: persistent cursor */
249 /**************************************************************//**
250 The position of the cursor is stored by taking an initial segment of the
251 record the cursor is positioned on, before, or after, and copying it to the
252 cursor data structure, or just setting a flag if the cursor id before the
253 first in an EMPTY tree, or after the last in an EMPTY tree. NOTE that the
254 page where the cursor is positioned must not be empty if the index tree is
255 not totally empty! */
256 void
257 btr_pcur_store_position(
258 /*====================*/
259 	btr_pcur_t*	cursor, /*!< in: persistent cursor */
260 	mtr_t*		mtr);	/*!< in: mtr */
261 /**************************************************************//**
262 Restores the stored position of a persistent cursor bufferfixing the page and
263 obtaining the specified latches. If the cursor position was saved when the
264 (1) cursor was positioned on a user record: this function restores the position
265 to the last record LESS OR EQUAL to the stored record;
266 (2) cursor was positioned on a page infimum record: restores the position to
267 the last record LESS than the user record which was the successor of the page
268 infimum;
269 (3) cursor was positioned on the page supremum: restores to the first record
270 GREATER than the user record which was the predecessor of the supremum.
271 (4) cursor was positioned before the first or after the last in an empty tree:
272 restores to before first or after the last in the tree.
273 @return TRUE if the cursor position was stored when it was on a user
274 record and it can be restored on a user record whose ordering fields
275 are identical to the ones of the original user record */
276 ibool
277 btr_pcur_restore_position_func(
278 /*===========================*/
279 	ulint		latch_mode,	/*!< in: BTR_SEARCH_LEAF, ... */
280 	btr_pcur_t*	cursor,		/*!< in: detached persistent cursor */
281 	const char*	file,		/*!< in: file name */
282 	ulint		line,		/*!< in: line where called */
283 	mtr_t*		mtr);		/*!< in: mtr */
284 #define btr_pcur_restore_position(l,cur,mtr)				\
285 	btr_pcur_restore_position_func(l,cur,__FILE__,__LINE__,mtr)
286 /*********************************************************//**
287 Gets the rel_pos field for a cursor whose position has been stored.
288 @return BTR_PCUR_ON, ... */
289 UNIV_INLINE
290 ulint
291 btr_pcur_get_rel_pos(
292 /*=================*/
293 	const btr_pcur_t*	cursor);/*!< in: persistent cursor */
294 /**************************************************************//**
295 Commits the mtr and sets the pcur latch mode to BTR_NO_LATCHES,
296 that is, the cursor becomes detached.
297 Function btr_pcur_store_position should be used before calling this,
298 if restoration of cursor is wanted later. */
299 UNIV_INLINE
300 void
301 btr_pcur_commit_specify_mtr(
302 /*========================*/
303 	btr_pcur_t*	pcur,	/*!< in: persistent cursor */
304 	mtr_t*		mtr);	/*!< in: mtr to commit */
305 /*********************************************************//**
306 Moves the persistent cursor to the next record in the tree. If no records are
307 left, the cursor stays 'after last in tree'.
308 @return TRUE if the cursor was not after last in tree */
309 UNIV_INLINE
310 ibool
311 btr_pcur_move_to_next(
312 /*==================*/
313 	btr_pcur_t*	cursor,	/*!< in: persistent cursor; NOTE that the
314 				function may release the page latch */
315 	mtr_t*		mtr);	/*!< in: mtr */
316 /*********************************************************//**
317 Moves the persistent cursor to the previous record in the tree. If no records
318 are left, the cursor stays 'before first in tree'.
319 @return TRUE if the cursor was not before first in tree */
320 ibool
321 btr_pcur_move_to_prev(
322 /*==================*/
323 	btr_pcur_t*	cursor,	/*!< in: persistent cursor; NOTE that the
324 				function may release the page latch */
325 	mtr_t*		mtr);	/*!< in: mtr */
326 /*********************************************************//**
327 Moves the persistent cursor to the last record on the same page. */
328 UNIV_INLINE
329 void
330 btr_pcur_move_to_last_on_page(
331 /*==========================*/
332 	btr_pcur_t*	cursor,	/*!< in: persistent cursor */
333 	mtr_t*		mtr);	/*!< in: mtr */
334 /*********************************************************//**
335 Moves the persistent cursor to the next user record in the tree. If no user
336 records are left, the cursor ends up 'after last in tree'.
337 @return TRUE if the cursor moved forward, ending on a user record */
338 UNIV_INLINE
339 ibool
340 btr_pcur_move_to_next_user_rec(
341 /*===========================*/
342 	btr_pcur_t*	cursor,	/*!< in: persistent cursor; NOTE that the
343 				function may release the page latch */
344 	mtr_t*		mtr);	/*!< in: mtr */
345 /*********************************************************//**
346 Moves the persistent cursor to the first record on the next page.
347 Releases the latch on the current page, and bufferunfixes it.
348 Note that there must not be modifications on the current page,
349 as then the x-latch can be released only in mtr_commit. */
350 void
351 btr_pcur_move_to_next_page(
352 /*=======================*/
353 	btr_pcur_t*	cursor,	/*!< in: persistent cursor; must be on the
354 				last record of the current page */
355 	mtr_t*		mtr);	/*!< in: mtr */
356 /*********************************************************//**
357 Moves the persistent cursor backward if it is on the first record
358 of the page. Releases the latch on the current page, and bufferunfixes
359 it. Note that to prevent a possible deadlock, the operation first
360 stores the position of the cursor, releases the leaf latch, acquires
361 necessary latches and restores the cursor position again before returning.
362 The alphabetical position of the cursor is guaranteed to be sensible
363 on return, but it may happen that the cursor is not positioned on the
364 last record of any page, because the structure of the tree may have
365 changed while the cursor had no latches. */
366 void
367 btr_pcur_move_backward_from_page(
368 /*=============================*/
369 	btr_pcur_t*	cursor,	/*!< in: persistent cursor, must be on the
370 				first record of the current page */
371 	mtr_t*		mtr);	/*!< in: mtr */
372 #ifdef UNIV_DEBUG
373 /*********************************************************//**
374 Returns the btr cursor component of a persistent cursor.
375 @return pointer to btr cursor component */
376 UNIV_INLINE
377 btr_cur_t*
378 btr_pcur_get_btr_cur(
379 /*=================*/
380 	const btr_pcur_t*	cursor);	/*!< in: persistent cursor */
381 /*********************************************************//**
382 Returns the page cursor component of a persistent cursor.
383 @return pointer to page cursor component */
384 UNIV_INLINE
385 page_cur_t*
386 btr_pcur_get_page_cur(
387 /*==================*/
388 	const btr_pcur_t*	cursor);	/*!< in: persistent cursor */
389 /*********************************************************//**
390 Returns the page of a persistent cursor.
391 @return pointer to the page */
392 UNIV_INLINE
393 page_t*
394 btr_pcur_get_page(
395 /*==============*/
396 	const btr_pcur_t*	cursor);/*!< in: persistent cursor */
397 /*********************************************************//**
398 Returns the buffer block of a persistent cursor.
399 @return pointer to the block */
400 UNIV_INLINE
401 buf_block_t*
402 btr_pcur_get_block(
403 /*===============*/
404 	const btr_pcur_t*	cursor);/*!< in: persistent cursor */
405 /*********************************************************//**
406 Returns the record of a persistent cursor.
407 @return pointer to the record */
408 UNIV_INLINE
409 rec_t*
410 btr_pcur_get_rec(
411 /*=============*/
412 	const btr_pcur_t*	cursor);/*!< in: persistent cursor */
413 #else /* UNIV_DEBUG */
414 # define btr_pcur_get_btr_cur(cursor) (&(cursor)->btr_cur)
415 # define btr_pcur_get_page_cur(cursor) (&(cursor)->btr_cur.page_cur)
416 # define btr_pcur_get_page(cursor) ((cursor)->btr_cur.page_cur.block->frame)
417 # define btr_pcur_get_block(cursor) ((cursor)->btr_cur.page_cur.block)
418 # define btr_pcur_get_rec(cursor) ((cursor)->btr_cur.page_cur.rec)
419 #endif /* UNIV_DEBUG */
420 /*********************************************************//**
421 Checks if the persistent cursor is on a user record. */
422 UNIV_INLINE
423 ibool
424 btr_pcur_is_on_user_rec(
425 /*====================*/
426 	const btr_pcur_t*	cursor);/*!< in: persistent cursor */
427 /*********************************************************//**
428 Checks if the persistent cursor is after the last user record on
429 a page. */
430 UNIV_INLINE
431 ibool
432 btr_pcur_is_after_last_on_page(
433 /*===========================*/
434 	const btr_pcur_t*	cursor);/*!< in: persistent cursor */
435 /*********************************************************//**
436 Checks if the persistent cursor is before the first user record on
437 a page. */
438 UNIV_INLINE
439 ibool
440 btr_pcur_is_before_first_on_page(
441 /*=============================*/
442 	const btr_pcur_t*	cursor);/*!< in: persistent cursor */
443 /*********************************************************//**
444 Checks if the persistent cursor is before the first user record in
445 the index tree. */
446 UNIV_INLINE
447 ibool
448 btr_pcur_is_before_first_in_tree(
449 /*=============================*/
450 	btr_pcur_t*	cursor,	/*!< in: persistent cursor */
451 	mtr_t*		mtr);	/*!< in: mtr */
452 /*********************************************************//**
453 Checks if the persistent cursor is after the last user record in
454 the index tree. */
455 UNIV_INLINE
456 ibool
457 btr_pcur_is_after_last_in_tree(
458 /*===========================*/
459 	btr_pcur_t*	cursor,	/*!< in: persistent cursor */
460 	mtr_t*		mtr);	/*!< in: mtr */
461 /*********************************************************//**
462 Moves the persistent cursor to the next record on the same page. */
463 UNIV_INLINE
464 void
465 btr_pcur_move_to_next_on_page(
466 /*==========================*/
467 	btr_pcur_t*	cursor);/*!< in/out: persistent cursor */
468 /*********************************************************//**
469 Moves the persistent cursor to the previous record on the same page. */
470 UNIV_INLINE
471 void
472 btr_pcur_move_to_prev_on_page(
473 /*==========================*/
474 	btr_pcur_t*	cursor);/*!< in/out: persistent cursor */
475 /*********************************************************//**
476 Moves the persistent cursor to the infimum record on the same page. */
477 UNIV_INLINE
478 void
479 btr_pcur_move_before_first_on_page(
480 /*===============================*/
481 	btr_pcur_t*	cursor); /*!< in/out: persistent cursor */
482 
483 /** Position state of persistent B-tree cursor. */
484 enum pcur_pos_t {
485 	/** The persistent cursor is not positioned. */
486 	BTR_PCUR_NOT_POSITIONED = 0,
487 	/** The persistent cursor was previously positioned.
488 	TODO: currently, the state can be BTR_PCUR_IS_POSITIONED,
489 	though it really should be BTR_PCUR_WAS_POSITIONED,
490 	because we have no obligation to commit the cursor with
491 	mtr; similarly latch_mode may be out of date. This can
492 	lead to problems if btr_pcur is not used the right way;
493 	all current code should be ok. */
494 	BTR_PCUR_WAS_POSITIONED,
495 	/** The persistent cursor is positioned by optimistic get to the same
496 	record as it was positioned at. Not used for rel_pos == BTR_PCUR_ON.
497 	It may need adjustment depending on previous/current search direction
498 	and rel_pos. */
499 	BTR_PCUR_IS_POSITIONED_OPTIMISTIC,
500 	/** The persistent cursor is positioned by index search.
501 	Or optimistic get for rel_pos == BTR_PCUR_ON. */
502 	BTR_PCUR_IS_POSITIONED
503 };
504 
505 /* Import tablespace context for persistent B-tree cursor. */
506 struct import_ctx_t{
507 	/* true if cursor fails to move to the next page during import. */
508 	bool	is_error;
509 };
510 
511 /* The persistent B-tree cursor structure. This is used mainly for SQL
512 selects, updates, and deletes. */
513 
514 struct btr_pcur_t{
btr_pcur_tbtr_pcur_t515 	btr_pcur_t() { memset(this, 0, sizeof(*this)); }
516 
517 	/** a B-tree cursor */
518 	btr_cur_t	btr_cur;
519 	/** see TODO note below!
520 	BTR_SEARCH_LEAF, BTR_MODIFY_LEAF, BTR_MODIFY_TREE or BTR_NO_LATCHES,
521 	depending on the latching state of the page and tree where the cursor
522 	is positioned; BTR_NO_LATCHES means that the cursor is not currently
523 	positioned:
524 	we say then that the cursor is detached; it can be restored to
525 	attached if the old position was stored in old_rec */
526 	ulint		latch_mode;
527 	/** true if old_rec is stored */
528 	bool		old_stored;
529 	/** if cursor position is stored, contains an initial segment of the
530 	latest record cursor was positioned either on, before or after */
531 	rec_t*		old_rec;
532 	/** number of fields in old_rec */
533 	ulint		old_n_fields;
534 	/** BTR_PCUR_ON, BTR_PCUR_BEFORE, or BTR_PCUR_AFTER, depending on
535 	whether cursor was on, before, or after the old_rec record */
536 	enum btr_pcur_pos_t	rel_pos;
537 	/** buffer block when the position was stored */
538 	buf::Block_hint	block_when_stored;
539 	/** the modify clock value of the buffer block when the cursor position
540 	was stored */
541 	ib_uint64_t	modify_clock;
542 
543 	/** btr_pcur_store_position() and btr_pcur_restore_position() state. */
544 	enum pcur_pos_t	pos_state;
545 	/** PAGE_CUR_G, ... */
546 	page_cur_mode_t	search_mode;
547 	/** the transaction, if we know it; otherwise this field is not defined;
548 	can ONLY BE USED in error prints in fatal assertion failures! */
549 	trx_t*		trx_if_known;
550 	/*-----------------------------*/
551 	/* NOTE that the following fields may possess dynamically allocated
552 	memory which should be freed if not needed anymore! */
553 
554 	/** NULL, or a dynamically allocated buffer for old_rec */
555 	byte*		old_rec_buf;
556 	/** old_rec_buf size if old_rec_buf is not NULL */
557 	ulint		buf_size;
558 
559 	/* NOTE that the following field is initialized only during import
560 	tablespace, otherwise undefined */
561 	import_ctx_t*	import_ctx;
562 
563 	/** Return the index of this persistent cursor */
indexbtr_pcur_t564 	dict_index_t*	index() const { return(btr_cur.index); }
565 };
566 
567 #ifndef UNIV_NONINL
568 #include "btr0pcur.ic"
569 #endif
570 
571 #endif
572