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