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