1 /***************************************************************************** 2 3 Copyright (c) 1994, 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/rem0rec.h 29 Record manager 30 31 Created 5/30/1994 Heikki Tuuri 32 *************************************************************************/ 33 34 #ifndef rem0rec_h 35 #define rem0rec_h 36 37 #include "univ.i" 38 #include "data0data.h" 39 #include "rem0types.h" 40 #include "mtr0types.h" 41 #include "page0types.h" 42 43 /* Info bit denoting the predefined minimum record: this bit is set 44 if and only if the record is the first user record on a non-leaf 45 B-tree page that is the leftmost page on its level 46 (PAGE_LEVEL is nonzero and FIL_PAGE_PREV is FIL_NULL). */ 47 #define REC_INFO_MIN_REC_FLAG 0x10UL 48 /* The deleted flag in info bits */ 49 #define REC_INFO_DELETED_FLAG 0x20UL /* when bit is set to 1, it means the 50 record has been delete marked */ 51 52 /* Number of extra bytes in an old-style record, 53 in addition to the data and the offsets */ 54 #define REC_N_OLD_EXTRA_BYTES 6 55 /* Number of extra bytes in a new-style record, 56 in addition to the data and the offsets */ 57 #define REC_N_NEW_EXTRA_BYTES 5 58 59 /* Record status values */ 60 #define REC_STATUS_ORDINARY 0 61 #define REC_STATUS_NODE_PTR 1 62 #define REC_STATUS_INFIMUM 2 63 #define REC_STATUS_SUPREMUM 3 64 65 /* The following four constants are needed in page0zip.cc in order to 66 efficiently compress and decompress pages. */ 67 68 /* The offset of heap_no in a compact record */ 69 #define REC_NEW_HEAP_NO 4 70 /* The shift of heap_no in a compact record. 71 The status is stored in the low-order bits. */ 72 #define REC_HEAP_NO_SHIFT 3 73 74 /* Length of a B-tree node pointer, in bytes */ 75 #define REC_NODE_PTR_SIZE 4 76 77 /** SQL null flag in a 1-byte offset of ROW_FORMAT=REDUNDANT records */ 78 #define REC_1BYTE_SQL_NULL_MASK 0x80UL 79 /** SQL null flag in a 2-byte offset of ROW_FORMAT=REDUNDANT records */ 80 #define REC_2BYTE_SQL_NULL_MASK 0x8000UL 81 82 /** In a 2-byte offset of ROW_FORMAT=REDUNDANT records, the second most 83 significant bit denotes that the tail of a field is stored off-page. */ 84 #define REC_2BYTE_EXTERN_MASK 0x4000UL 85 86 #ifdef UNIV_DEBUG 87 /* Length of the rec_get_offsets() header */ 88 # define REC_OFFS_HEADER_SIZE 4 89 #else /* UNIV_DEBUG */ 90 /* Length of the rec_get_offsets() header */ 91 # define REC_OFFS_HEADER_SIZE 2 92 #endif /* UNIV_DEBUG */ 93 94 /* Number of elements that should be initially allocated for the 95 offsets[] array, first passed to rec_get_offsets() */ 96 #define REC_OFFS_NORMAL_SIZE 100 97 #define REC_OFFS_SMALL_SIZE 10 98 99 /******************************************************//** 100 The following function is used to get the pointer of the next chained record 101 on the same page. 102 @return pointer to the next chained record, or NULL if none */ 103 UNIV_INLINE 104 const rec_t* 105 rec_get_next_ptr_const( 106 /*===================*/ 107 const rec_t* rec, /*!< in: physical record */ 108 ulint comp) /*!< in: nonzero=compact page format */ 109 MY_ATTRIBUTE((nonnull, pure, warn_unused_result)); 110 /******************************************************//** 111 The following function is used to get the pointer of the next chained record 112 on the same page. 113 @return pointer to the next chained record, or NULL if none */ 114 UNIV_INLINE 115 rec_t* 116 rec_get_next_ptr( 117 /*=============*/ 118 rec_t* rec, /*!< in: physical record */ 119 ulint comp) /*!< in: nonzero=compact page format */ 120 MY_ATTRIBUTE((nonnull, pure, warn_unused_result)); 121 /******************************************************//** 122 The following function is used to get the offset of the 123 next chained record on the same page. 124 @return the page offset of the next chained record, or 0 if none */ 125 UNIV_INLINE 126 ulint 127 rec_get_next_offs( 128 /*==============*/ 129 const rec_t* rec, /*!< in: physical record */ 130 ulint comp) /*!< in: nonzero=compact page format */ 131 MY_ATTRIBUTE((nonnull, pure, warn_unused_result)); 132 /******************************************************//** 133 The following function is used to set the next record offset field 134 of an old-style record. */ 135 UNIV_INLINE 136 void 137 rec_set_next_offs_old( 138 /*==================*/ 139 rec_t* rec, /*!< in: old-style physical record */ 140 ulint next) /*!< in: offset of the next record */ 141 MY_ATTRIBUTE((nonnull)); 142 /******************************************************//** 143 The following function is used to set the next record offset field 144 of a new-style record. */ 145 UNIV_INLINE 146 void 147 rec_set_next_offs_new( 148 /*==================*/ 149 rec_t* rec, /*!< in/out: new-style physical record */ 150 ulint next) /*!< in: offset of the next record */ 151 MY_ATTRIBUTE((nonnull)); 152 /******************************************************//** 153 The following function is used to get the number of fields 154 in an old-style record. 155 @return number of data fields */ 156 UNIV_INLINE 157 ulint 158 rec_get_n_fields_old( 159 /*=================*/ 160 const rec_t* rec) /*!< in: physical record */ 161 MY_ATTRIBUTE((nonnull, pure, warn_unused_result)); 162 /******************************************************//** 163 The following function is used to get the number of fields 164 in a record. 165 @return number of data fields */ 166 UNIV_INLINE 167 ulint 168 rec_get_n_fields( 169 /*=============*/ 170 const rec_t* rec, /*!< in: physical record */ 171 const dict_index_t* index) /*!< in: record descriptor */ 172 MY_ATTRIBUTE((nonnull, pure, warn_unused_result)); 173 /******************************************************//** 174 The following function is used to get the number of records owned by the 175 previous directory record. 176 @return number of owned records */ 177 UNIV_INLINE 178 ulint 179 rec_get_n_owned_old( 180 /*================*/ 181 const rec_t* rec) /*!< in: old-style physical record */ 182 MY_ATTRIBUTE((nonnull, pure, warn_unused_result)); 183 /******************************************************//** 184 The following function is used to set the number of owned records. */ 185 UNIV_INLINE 186 void 187 rec_set_n_owned_old( 188 /*================*/ 189 rec_t* rec, /*!< in: old-style physical record */ 190 ulint n_owned) /*!< in: the number of owned */ 191 MY_ATTRIBUTE((nonnull)); 192 /******************************************************//** 193 The following function is used to get the number of records owned by the 194 previous directory record. 195 @return number of owned records */ 196 UNIV_INLINE 197 ulint 198 rec_get_n_owned_new( 199 /*================*/ 200 const rec_t* rec) /*!< in: new-style physical record */ 201 MY_ATTRIBUTE((nonnull, pure, warn_unused_result)); 202 /******************************************************//** 203 The following function is used to set the number of owned records. */ 204 UNIV_INLINE 205 void 206 rec_set_n_owned_new( 207 /*================*/ 208 rec_t* rec, /*!< in/out: new-style physical record */ 209 page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */ 210 ulint n_owned)/*!< in: the number of owned */ 211 MY_ATTRIBUTE((nonnull(1))); 212 /******************************************************//** 213 The following function is used to retrieve the info bits of 214 a record. 215 @return info bits */ 216 UNIV_INLINE 217 ulint 218 rec_get_info_bits( 219 /*==============*/ 220 const rec_t* rec, /*!< in: physical record */ 221 ulint comp) /*!< in: nonzero=compact page format */ 222 MY_ATTRIBUTE((nonnull, pure, warn_unused_result)); 223 /******************************************************//** 224 The following function is used to set the info bits of a record. */ 225 UNIV_INLINE 226 void 227 rec_set_info_bits_old( 228 /*==================*/ 229 rec_t* rec, /*!< in: old-style physical record */ 230 ulint bits) /*!< in: info bits */ 231 MY_ATTRIBUTE((nonnull)); 232 /******************************************************//** 233 The following function is used to set the info bits of a record. */ 234 UNIV_INLINE 235 void 236 rec_set_info_bits_new( 237 /*==================*/ 238 rec_t* rec, /*!< in/out: new-style physical record */ 239 ulint bits) /*!< in: info bits */ 240 MY_ATTRIBUTE((nonnull)); 241 /******************************************************//** 242 The following function retrieves the status bits of a new-style record. 243 @return status bits */ 244 UNIV_INLINE 245 ulint 246 rec_get_status( 247 /*===========*/ 248 const rec_t* rec) /*!< in: physical record */ 249 MY_ATTRIBUTE((nonnull, pure, warn_unused_result)); 250 251 /******************************************************//** 252 The following function is used to set the status bits of a new-style record. */ 253 UNIV_INLINE 254 void 255 rec_set_status( 256 /*===========*/ 257 rec_t* rec, /*!< in/out: physical record */ 258 ulint bits) /*!< in: info bits */ 259 MY_ATTRIBUTE((nonnull)); 260 261 /******************************************************//** 262 The following function is used to retrieve the info and status 263 bits of a record. (Only compact records have status bits.) 264 @return info bits */ 265 UNIV_INLINE 266 ulint 267 rec_get_info_and_status_bits( 268 /*=========================*/ 269 const rec_t* rec, /*!< in: physical record */ 270 ulint comp) /*!< in: nonzero=compact page format */ 271 MY_ATTRIBUTE((nonnull, pure, warn_unused_result)); 272 /******************************************************//** 273 The following function is used to set the info and status 274 bits of a record. (Only compact records have status bits.) */ 275 UNIV_INLINE 276 void 277 rec_set_info_and_status_bits( 278 /*=========================*/ 279 rec_t* rec, /*!< in/out: compact physical record */ 280 ulint bits) /*!< in: info bits */ 281 MY_ATTRIBUTE((nonnull)); 282 283 /******************************************************//** 284 The following function tells if record is delete marked. 285 @return nonzero if delete marked */ 286 UNIV_INLINE 287 ulint 288 rec_get_deleted_flag( 289 /*=================*/ 290 const rec_t* rec, /*!< in: physical record */ 291 ulint comp) /*!< in: nonzero=compact page format */ 292 MY_ATTRIBUTE((nonnull, pure, warn_unused_result)); 293 /******************************************************//** 294 The following function is used to set the deleted bit. */ 295 UNIV_INLINE 296 void 297 rec_set_deleted_flag_old( 298 /*=====================*/ 299 rec_t* rec, /*!< in: old-style physical record */ 300 ulint flag) /*!< in: nonzero if delete marked */ 301 MY_ATTRIBUTE((nonnull)); 302 /******************************************************//** 303 The following function is used to set the deleted bit. */ 304 UNIV_INLINE 305 void 306 rec_set_deleted_flag_new( 307 /*=====================*/ 308 rec_t* rec, /*!< in/out: new-style physical record */ 309 page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */ 310 ulint flag) /*!< in: nonzero if delete marked */ 311 MY_ATTRIBUTE((nonnull(1))); 312 /******************************************************//** 313 The following function tells if a new-style record is a node pointer. 314 @return TRUE if node pointer */ 315 UNIV_INLINE 316 ibool 317 rec_get_node_ptr_flag( 318 /*==================*/ 319 const rec_t* rec) /*!< in: physical record */ 320 MY_ATTRIBUTE((nonnull, pure, warn_unused_result)); 321 /******************************************************//** 322 The following function is used to get the order number 323 of an old-style record in the heap of the index page. 324 @return heap order number */ 325 UNIV_INLINE 326 ulint 327 rec_get_heap_no_old( 328 /*================*/ 329 const rec_t* rec) /*!< in: physical record */ 330 MY_ATTRIBUTE((nonnull, pure, warn_unused_result)); 331 /******************************************************//** 332 The following function is used to set the heap number 333 field in an old-style record. */ 334 UNIV_INLINE 335 void 336 rec_set_heap_no_old( 337 /*================*/ 338 rec_t* rec, /*!< in: physical record */ 339 ulint heap_no)/*!< in: the heap number */ 340 MY_ATTRIBUTE((nonnull)); 341 /******************************************************//** 342 The following function is used to get the order number 343 of a new-style record in the heap of the index page. 344 @return heap order number */ 345 UNIV_INLINE 346 ulint 347 rec_get_heap_no_new( 348 /*================*/ 349 const rec_t* rec) /*!< in: physical record */ 350 MY_ATTRIBUTE((nonnull, pure, warn_unused_result)); 351 /******************************************************//** 352 The following function is used to set the heap number 353 field in a new-style record. */ 354 UNIV_INLINE 355 void 356 rec_set_heap_no_new( 357 /*================*/ 358 rec_t* rec, /*!< in/out: physical record */ 359 ulint heap_no)/*!< in: the heap number */ 360 MY_ATTRIBUTE((nonnull)); 361 /******************************************************//** 362 The following function is used to test whether the data offsets 363 in the record are stored in one-byte or two-byte format. 364 @return TRUE if 1-byte form */ 365 UNIV_INLINE 366 ibool 367 rec_get_1byte_offs_flag( 368 /*====================*/ 369 const rec_t* rec) /*!< in: physical record */ 370 MY_ATTRIBUTE((nonnull, pure, warn_unused_result)); 371 372 /******************************************************//** 373 The following function is used to set the 1-byte offsets flag. */ 374 UNIV_INLINE 375 void 376 rec_set_1byte_offs_flag( 377 /*====================*/ 378 rec_t* rec, /*!< in: physical record */ 379 ibool flag) /*!< in: TRUE if 1byte form */ 380 MY_ATTRIBUTE((nonnull)); 381 382 /******************************************************//** 383 Returns the offset of nth field end if the record is stored in the 1-byte 384 offsets form. If the field is SQL null, the flag is ORed in the returned 385 value. 386 @return offset of the start of the field, SQL null flag ORed */ 387 UNIV_INLINE 388 ulint 389 rec_1_get_field_end_info( 390 /*=====================*/ 391 const rec_t* rec, /*!< in: record */ 392 ulint n) /*!< in: field index */ 393 MY_ATTRIBUTE((nonnull, pure, warn_unused_result)); 394 395 /******************************************************//** 396 Returns the offset of nth field end if the record is stored in the 2-byte 397 offsets form. If the field is SQL null, the flag is ORed in the returned 398 value. 399 @return offset of the start of the field, SQL null flag and extern 400 storage flag ORed */ 401 UNIV_INLINE 402 ulint 403 rec_2_get_field_end_info( 404 /*=====================*/ 405 const rec_t* rec, /*!< in: record */ 406 ulint n) /*!< in: field index */ 407 MY_ATTRIBUTE((nonnull, pure, warn_unused_result)); 408 409 /******************************************************//** 410 Returns nonzero if the field is stored off-page. 411 @retval 0 if the field is stored in-page 412 @retval REC_2BYTE_EXTERN_MASK if the field is stored externally */ 413 UNIV_INLINE 414 ulint 415 rec_2_is_field_extern( 416 /*==================*/ 417 const rec_t* rec, /*!< in: record */ 418 ulint n) /*!< in: field index */ 419 MY_ATTRIBUTE((nonnull, pure, warn_unused_result)); 420 421 /******************************************************//** 422 Determine how many of the first n columns in a compact 423 physical record are stored externally. 424 @return number of externally stored columns */ 425 UNIV_INTERN 426 ulint 427 rec_get_n_extern_new( 428 /*=================*/ 429 const rec_t* rec, /*!< in: compact physical record */ 430 const dict_index_t* index, /*!< in: record descriptor */ 431 ulint n) /*!< in: number of columns to scan */ 432 MY_ATTRIBUTE((nonnull, warn_unused_result)); 433 434 /******************************************************//** 435 The following function determines the offsets to each field 436 in the record. It can reuse a previously allocated array. 437 @return the new offsets */ 438 UNIV_INTERN 439 ulint* 440 rec_get_offsets_func( 441 /*=================*/ 442 const rec_t* rec, /*!< in: physical record */ 443 const dict_index_t* index, /*!< in: record descriptor */ 444 ulint* offsets,/*!< in/out: array consisting of 445 offsets[0] allocated elements, 446 or an array from rec_get_offsets(), 447 or NULL */ 448 ulint n_fields,/*!< in: maximum number of 449 initialized fields 450 (ULINT_UNDEFINED if all fields) */ 451 #ifdef UNIV_DEBUG 452 const char* file, /*!< in: file name where called */ 453 ulint line, /*!< in: line number where called */ 454 #endif /* UNIV_DEBUG */ 455 mem_heap_t** heap) /*!< in/out: memory heap */ 456 #ifdef UNIV_DEBUG 457 MY_ATTRIBUTE((nonnull(1,2,5,7),warn_unused_result)); 458 #else /* UNIV_DEBUG */ 459 MY_ATTRIBUTE((nonnull(1,2,5),warn_unused_result)); 460 #endif /* UNIV_DEBUG */ 461 462 #ifdef UNIV_DEBUG 463 # define rec_get_offsets(rec,index,offsets,n,heap) \ 464 rec_get_offsets_func(rec,index,offsets,n,__FILE__,__LINE__,heap) 465 #else /* UNIV_DEBUG */ 466 # define rec_get_offsets(rec, index, offsets, n, heap) \ 467 rec_get_offsets_func(rec, index, offsets, n, heap) 468 #endif /* UNIV_DEBUG */ 469 470 /******************************************************//** 471 The following function determines the offsets to each field 472 in the record. It can reuse a previously allocated array. */ 473 UNIV_INTERN 474 void 475 rec_get_offsets_reverse( 476 /*====================*/ 477 const byte* extra, /*!< in: the extra bytes of a 478 compact record in reverse order, 479 excluding the fixed-size 480 REC_N_NEW_EXTRA_BYTES */ 481 const dict_index_t* index, /*!< in: record descriptor */ 482 ulint node_ptr,/*!< in: nonzero=node pointer, 483 0=leaf node */ 484 ulint* offsets)/*!< in/out: array consisting of 485 offsets[0] allocated elements */ 486 MY_ATTRIBUTE((nonnull)); 487 #ifdef UNIV_DEBUG 488 /************************************************************//** 489 Validates offsets returned by rec_get_offsets(). 490 @return TRUE if valid */ 491 UNIV_INLINE 492 ibool 493 rec_offs_validate( 494 /*==============*/ 495 const rec_t* rec, /*!< in: record or NULL */ 496 const dict_index_t* index, /*!< in: record descriptor or NULL */ 497 const ulint* offsets)/*!< in: array returned by 498 rec_get_offsets() */ 499 MY_ATTRIBUTE((nonnull(3), warn_unused_result)); 500 /************************************************************//** 501 Updates debug data in offsets, in order to avoid bogus 502 rec_offs_validate() failures. */ 503 UNIV_INLINE 504 void 505 rec_offs_make_valid( 506 /*================*/ 507 const rec_t* rec, /*!< in: record */ 508 const dict_index_t* index, /*!< in: record descriptor */ 509 ulint* offsets)/*!< in: array returned by 510 rec_get_offsets() */ 511 MY_ATTRIBUTE((nonnull)); 512 #else 513 # define rec_offs_make_valid(rec, index, offsets) ((void) 0) 514 #endif /* UNIV_DEBUG */ 515 516 /************************************************************//** 517 The following function is used to get the offset to the nth 518 data field in an old-style record. 519 @return offset to the field */ 520 UNIV_INTERN 521 ulint 522 rec_get_nth_field_offs_old( 523 /*=======================*/ 524 const rec_t* rec, /*!< in: record */ 525 ulint n, /*!< in: index of the field */ 526 ulint* len) /*!< out: length of the field; UNIV_SQL_NULL 527 if SQL null */ 528 MY_ATTRIBUTE((nonnull)); 529 #define rec_get_nth_field_old(rec, n, len) \ 530 ((rec) + rec_get_nth_field_offs_old(rec, n, len)) 531 /************************************************************//** 532 Gets the physical size of an old-style field. 533 Also an SQL null may have a field of size > 0, 534 if the data type is of a fixed size. 535 @return field size in bytes */ 536 UNIV_INLINE 537 ulint 538 rec_get_nth_field_size( 539 /*===================*/ 540 const rec_t* rec, /*!< in: record */ 541 ulint n) /*!< in: index of the field */ 542 MY_ATTRIBUTE((nonnull, pure, warn_unused_result)); 543 /************************************************************//** 544 The following function is used to get an offset to the nth 545 data field in a record. 546 @return offset from the origin of rec */ 547 UNIV_INLINE 548 ulint 549 rec_get_nth_field_offs( 550 /*===================*/ 551 const ulint* offsets,/*!< in: array returned by rec_get_offsets() */ 552 ulint n, /*!< in: index of the field */ 553 ulint* len) /*!< out: length of the field; UNIV_SQL_NULL 554 if SQL null */ 555 MY_ATTRIBUTE((nonnull)); 556 #define rec_get_nth_field(rec, offsets, n, len) \ 557 ((rec) + rec_get_nth_field_offs(offsets, n, len)) 558 /******************************************************//** 559 Determine if the offsets are for a record in the new 560 compact format. 561 @return nonzero if compact format */ 562 UNIV_INLINE 563 ulint 564 rec_offs_comp( 565 /*==========*/ 566 const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ 567 MY_ATTRIBUTE((nonnull, pure, warn_unused_result)); 568 /******************************************************//** 569 Determine if the offsets are for a record containing 570 externally stored columns. 571 @return nonzero if externally stored */ 572 UNIV_INLINE 573 ulint 574 rec_offs_any_extern( 575 /*================*/ 576 const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ 577 MY_ATTRIBUTE((nonnull, pure, warn_unused_result)); 578 /******************************************************//** 579 Determine if the offsets are for a record containing null BLOB pointers. 580 @return first field containing a null BLOB pointer, or NULL if none found */ 581 UNIV_INLINE 582 const byte* 583 rec_offs_any_null_extern( 584 /*=====================*/ 585 const rec_t* rec, /*!< in: record */ 586 const ulint* offsets) /*!< in: rec_get_offsets(rec) */ 587 MY_ATTRIBUTE((nonnull, pure, warn_unused_result)); 588 /******************************************************//** 589 Returns nonzero if the extern bit is set in nth field of rec. 590 @return nonzero if externally stored */ 591 UNIV_INLINE 592 ulint 593 rec_offs_nth_extern( 594 /*================*/ 595 const ulint* offsets,/*!< in: array returned by rec_get_offsets() */ 596 ulint n) /*!< in: nth field */ 597 MY_ATTRIBUTE((nonnull, pure, warn_unused_result)); 598 /******************************************************//** 599 Returns nonzero if the SQL NULL bit is set in nth field of rec. 600 @return nonzero if SQL NULL */ 601 UNIV_INLINE 602 ulint 603 rec_offs_nth_sql_null( 604 /*==================*/ 605 const ulint* offsets,/*!< in: array returned by rec_get_offsets() */ 606 ulint n) /*!< in: nth field */ 607 MY_ATTRIBUTE((nonnull, pure, warn_unused_result)); 608 /******************************************************//** 609 Gets the physical size of a field. 610 @return length of field */ 611 UNIV_INLINE 612 ulint 613 rec_offs_nth_size( 614 /*==============*/ 615 const ulint* offsets,/*!< in: array returned by rec_get_offsets() */ 616 ulint n) /*!< in: nth field */ 617 MY_ATTRIBUTE((nonnull, pure, warn_unused_result)); 618 619 /******************************************************//** 620 Returns the number of extern bits set in a record. 621 @return number of externally stored fields */ 622 UNIV_INLINE 623 ulint 624 rec_offs_n_extern( 625 /*==============*/ 626 const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ 627 MY_ATTRIBUTE((nonnull, pure, warn_unused_result)); 628 /***********************************************************//** 629 This is used to modify the value of an already existing field in a record. 630 The previous value must have exactly the same size as the new value. If len 631 is UNIV_SQL_NULL then the field is treated as an SQL null. 632 For records in ROW_FORMAT=COMPACT (new-style records), len must not be 633 UNIV_SQL_NULL unless the field already is SQL null. */ 634 UNIV_INLINE 635 void 636 rec_set_nth_field( 637 /*==============*/ 638 rec_t* rec, /*!< in: record */ 639 const ulint* offsets,/*!< in: array returned by rec_get_offsets() */ 640 ulint n, /*!< in: index number of the field */ 641 const void* data, /*!< in: pointer to the data if not SQL null */ 642 ulint len) /*!< in: length of the data or UNIV_SQL_NULL. 643 If not SQL null, must have the same 644 length as the previous value. 645 If SQL null, previous value must be 646 SQL null. */ 647 MY_ATTRIBUTE((nonnull(1,2))); 648 /**********************************************************//** 649 The following function returns the data size of an old-style physical 650 record, that is the sum of field lengths. SQL null fields 651 are counted as length 0 fields. The value returned by the function 652 is the distance from record origin to record end in bytes. 653 @return size */ 654 UNIV_INLINE 655 ulint 656 rec_get_data_size_old( 657 /*==================*/ 658 const rec_t* rec) /*!< in: physical record */ 659 MY_ATTRIBUTE((nonnull, pure, warn_unused_result)); 660 /**********************************************************//** 661 The following function returns the number of allocated elements 662 for an array of offsets. 663 @return number of elements */ 664 UNIV_INLINE 665 ulint 666 rec_offs_get_n_alloc( 667 /*=================*/ 668 const ulint* offsets)/*!< in: array for rec_get_offsets() */ 669 MY_ATTRIBUTE((nonnull, pure, warn_unused_result)); 670 /**********************************************************//** 671 The following function sets the number of allocated elements 672 for an array of offsets. */ 673 UNIV_INLINE 674 void 675 rec_offs_set_n_alloc( 676 /*=================*/ 677 ulint* offsets, /*!< out: array for rec_get_offsets(), 678 must be allocated */ 679 ulint n_alloc) /*!< in: number of elements */ 680 MY_ATTRIBUTE((nonnull)); 681 #define rec_offs_init(offsets) \ 682 rec_offs_set_n_alloc(offsets, (sizeof offsets) / sizeof *offsets) 683 /**********************************************************//** 684 The following function returns the number of fields in a record. 685 @return number of fields */ 686 UNIV_INLINE 687 ulint 688 rec_offs_n_fields( 689 /*==============*/ 690 const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ 691 MY_ATTRIBUTE((nonnull, pure, warn_unused_result)); 692 /**********************************************************//** 693 The following function returns the data size of a physical 694 record, that is the sum of field lengths. SQL null fields 695 are counted as length 0 fields. The value returned by the function 696 is the distance from record origin to record end in bytes. 697 @return size */ 698 UNIV_INLINE 699 ulint 700 rec_offs_data_size( 701 /*===============*/ 702 const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ 703 MY_ATTRIBUTE((nonnull, pure, warn_unused_result)); 704 /**********************************************************//** 705 Returns the total size of record minus data size of record. 706 The value returned by the function is the distance from record 707 start to record origin in bytes. 708 @return size */ 709 UNIV_INLINE 710 ulint 711 rec_offs_extra_size( 712 /*================*/ 713 const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ 714 MY_ATTRIBUTE((nonnull, pure, warn_unused_result)); 715 /**********************************************************//** 716 Returns the total size of a physical record. 717 @return size */ 718 UNIV_INLINE 719 ulint 720 rec_offs_size( 721 /*==========*/ 722 const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ 723 MY_ATTRIBUTE((nonnull, pure, warn_unused_result)); 724 #ifdef UNIV_DEBUG 725 /**********************************************************//** 726 Returns a pointer to the start of the record. 727 @return pointer to start */ 728 UNIV_INLINE 729 byte* 730 rec_get_start( 731 /*==========*/ 732 const rec_t* rec, /*!< in: pointer to record */ 733 const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ 734 MY_ATTRIBUTE((nonnull, pure, warn_unused_result)); 735 /**********************************************************//** 736 Returns a pointer to the end of the record. 737 @return pointer to end */ 738 UNIV_INLINE 739 byte* 740 rec_get_end( 741 /*========*/ 742 const rec_t* rec, /*!< in: pointer to record */ 743 const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ 744 MY_ATTRIBUTE((nonnull, pure, warn_unused_result)); 745 #else /* UNIV_DEBUG */ 746 # define rec_get_start(rec, offsets) ((rec) - rec_offs_extra_size(offsets)) 747 # define rec_get_end(rec, offsets) ((rec) + rec_offs_data_size(offsets)) 748 #endif /* UNIV_DEBUG */ 749 /***************************************************************//** 750 Copies a physical record to a buffer. 751 @return pointer to the origin of the copy */ 752 UNIV_INLINE 753 rec_t* 754 rec_copy( 755 /*=====*/ 756 void* buf, /*!< in: buffer */ 757 const rec_t* rec, /*!< in: physical record */ 758 const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ 759 MY_ATTRIBUTE((nonnull)); 760 #ifndef UNIV_HOTBACKUP 761 /**********************************************************//** 762 Determines the size of a data tuple prefix in a temporary file. 763 @return total size */ 764 UNIV_INTERN 765 ulint 766 rec_get_converted_size_temp( 767 /*========================*/ 768 const dict_index_t* index, /*!< in: record descriptor */ 769 const dfield_t* fields, /*!< in: array of data fields */ 770 ulint n_fields,/*!< in: number of data fields */ 771 ulint* extra) /*!< out: extra size */ 772 MY_ATTRIBUTE((warn_unused_result, nonnull)); 773 774 /******************************************************//** 775 Determine the offset to each field in temporary file. 776 @see rec_convert_dtuple_to_temp() */ 777 UNIV_INTERN 778 void 779 rec_init_offsets_temp( 780 /*==================*/ 781 const rec_t* rec, /*!< in: temporary file record */ 782 const dict_index_t* index, /*!< in: record descriptor */ 783 ulint* offsets)/*!< in/out: array of offsets; 784 in: n=rec_offs_n_fields(offsets) */ 785 MY_ATTRIBUTE((nonnull)); 786 787 /*********************************************************//** 788 Builds a temporary file record out of a data tuple. 789 @see rec_init_offsets_temp() */ 790 UNIV_INTERN 791 void 792 rec_convert_dtuple_to_temp( 793 /*=======================*/ 794 rec_t* rec, /*!< out: record */ 795 const dict_index_t* index, /*!< in: record descriptor */ 796 const dfield_t* fields, /*!< in: array of data fields */ 797 ulint n_fields) /*!< in: number of fields */ 798 MY_ATTRIBUTE((nonnull)); 799 800 /**************************************************************//** 801 Copies the first n fields of a physical record to a new physical record in 802 a buffer. 803 @return own: copied record */ 804 UNIV_INTERN 805 rec_t* 806 rec_copy_prefix_to_buf( 807 /*===================*/ 808 const rec_t* rec, /*!< in: physical record */ 809 const dict_index_t* index, /*!< in: record descriptor */ 810 ulint n_fields, /*!< in: number of fields 811 to copy */ 812 byte** buf, /*!< in/out: memory buffer 813 for the copied prefix, 814 or NULL */ 815 ulint* buf_size) /*!< in/out: buffer size */ 816 MY_ATTRIBUTE((nonnull)); 817 /************************************************************//** 818 Folds a prefix of a physical record to a ulint. 819 @return the folded value */ 820 UNIV_INLINE 821 ulint 822 rec_fold( 823 /*=====*/ 824 const rec_t* rec, /*!< in: the physical record */ 825 const ulint* offsets, /*!< in: array returned by 826 rec_get_offsets() */ 827 ulint n_fields, /*!< in: number of complete 828 fields to fold */ 829 ulint n_bytes, /*!< in: number of bytes to fold 830 in an incomplete last field */ 831 index_id_t tree_id) /*!< in: index tree id */ 832 MY_ATTRIBUTE((nonnull, pure, warn_unused_result)); 833 #endif /* !UNIV_HOTBACKUP */ 834 /*********************************************************//** 835 Builds a physical record out of a data tuple and 836 stores it into the given buffer. 837 @return pointer to the origin of physical record */ 838 UNIV_INTERN 839 rec_t* 840 rec_convert_dtuple_to_rec( 841 /*======================*/ 842 byte* buf, /*!< in: start address of the 843 physical record */ 844 const dict_index_t* index, /*!< in: record descriptor */ 845 const dtuple_t* dtuple, /*!< in: data tuple */ 846 ulint n_ext) /*!< in: number of 847 externally stored columns */ 848 MY_ATTRIBUTE((nonnull, warn_unused_result)); 849 /**********************************************************//** 850 Returns the extra size of an old-style physical record if we know its 851 data size and number of fields. 852 @return extra size */ 853 UNIV_INLINE 854 ulint 855 rec_get_converted_extra_size( 856 /*=========================*/ 857 ulint data_size, /*!< in: data size */ 858 ulint n_fields, /*!< in: number of fields */ 859 ulint n_ext) /*!< in: number of externally stored columns */ 860 MY_ATTRIBUTE((const)); 861 /**********************************************************//** 862 Determines the size of a data tuple prefix in ROW_FORMAT=COMPACT. 863 @return total size */ 864 UNIV_INTERN 865 ulint 866 rec_get_converted_size_comp_prefix( 867 /*===============================*/ 868 const dict_index_t* index, /*!< in: record descriptor */ 869 const dfield_t* fields, /*!< in: array of data fields */ 870 ulint n_fields,/*!< in: number of data fields */ 871 ulint* extra) /*!< out: extra size */ 872 MY_ATTRIBUTE((warn_unused_result, nonnull(1,2))); 873 /**********************************************************//** 874 Determines the size of a data tuple in ROW_FORMAT=COMPACT. 875 @return total size */ 876 UNIV_INTERN 877 ulint 878 rec_get_converted_size_comp( 879 /*========================*/ 880 const dict_index_t* index, /*!< in: record descriptor; 881 dict_table_is_comp() is 882 assumed to hold, even if 883 it does not */ 884 ulint status, /*!< in: status bits of the record */ 885 const dfield_t* fields, /*!< in: array of data fields */ 886 ulint n_fields,/*!< in: number of data fields */ 887 ulint* extra) /*!< out: extra size */ 888 MY_ATTRIBUTE((nonnull(1,3))); 889 /**********************************************************//** 890 The following function returns the size of a data tuple when converted to 891 a physical record. 892 @return size */ 893 UNIV_INLINE 894 ulint 895 rec_get_converted_size( 896 /*===================*/ 897 dict_index_t* index, /*!< in: record descriptor */ 898 const dtuple_t* dtuple, /*!< in: data tuple */ 899 ulint n_ext) /*!< in: number of externally stored columns */ 900 MY_ATTRIBUTE((warn_unused_result, nonnull)); 901 #ifndef UNIV_HOTBACKUP 902 /**************************************************************//** 903 Copies the first n fields of a physical record to a data tuple. 904 The fields are copied to the memory heap. */ 905 UNIV_INTERN 906 void 907 rec_copy_prefix_to_dtuple( 908 /*======================*/ 909 dtuple_t* tuple, /*!< out: data tuple */ 910 const rec_t* rec, /*!< in: physical record */ 911 const dict_index_t* index, /*!< in: record descriptor */ 912 ulint n_fields, /*!< in: number of fields 913 to copy */ 914 mem_heap_t* heap) /*!< in: memory heap */ 915 MY_ATTRIBUTE((nonnull)); 916 #endif /* !UNIV_HOTBACKUP */ 917 /***************************************************************//** 918 Validates the consistency of a physical record. 919 @return TRUE if ok */ 920 UNIV_INTERN 921 ibool 922 rec_validate( 923 /*=========*/ 924 const rec_t* rec, /*!< in: physical record */ 925 const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ 926 MY_ATTRIBUTE((nonnull)); 927 /***************************************************************//** 928 Prints an old-style physical record. */ 929 UNIV_INTERN 930 void 931 rec_print_old( 932 /*==========*/ 933 FILE* file, /*!< in: file where to print */ 934 const rec_t* rec) /*!< in: physical record */ 935 MY_ATTRIBUTE((nonnull)); 936 #ifndef UNIV_HOTBACKUP 937 /***************************************************************//** 938 Prints a physical record in ROW_FORMAT=COMPACT. Ignores the 939 record header. */ 940 UNIV_INTERN 941 void 942 rec_print_comp( 943 /*===========*/ 944 FILE* file, /*!< in: file where to print */ 945 const rec_t* rec, /*!< in: physical record */ 946 const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ 947 MY_ATTRIBUTE((nonnull)); 948 /***************************************************************//** 949 Prints a physical record. */ 950 UNIV_INTERN 951 void 952 rec_print_new( 953 /*==========*/ 954 FILE* file, /*!< in: file where to print */ 955 const rec_t* rec, /*!< in: physical record */ 956 const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ 957 MY_ATTRIBUTE((nonnull)); 958 /***************************************************************//** 959 Prints a physical record. */ 960 UNIV_INTERN 961 void 962 rec_print( 963 /*======*/ 964 FILE* file, /*!< in: file where to print */ 965 const rec_t* rec, /*!< in: physical record */ 966 const dict_index_t* index) /*!< in: record descriptor */ 967 MY_ATTRIBUTE((nonnull)); 968 969 # ifdef UNIV_DEBUG 970 /************************************************************//** 971 Reads the DB_TRX_ID of a clustered index record. 972 @return the value of DB_TRX_ID */ 973 UNIV_INTERN 974 trx_id_t 975 rec_get_trx_id( 976 /*===========*/ 977 const rec_t* rec, /*!< in: record */ 978 const dict_index_t* index) /*!< in: clustered index */ 979 MY_ATTRIBUTE((nonnull, warn_unused_result)); 980 # endif /* UNIV_DEBUG */ 981 #endif /* UNIV_HOTBACKUP */ 982 983 /* Maximum lengths for the data in a physical record if the offsets 984 are given in one byte (resp. two byte) format. */ 985 #define REC_1BYTE_OFFS_LIMIT 0x7FUL 986 #define REC_2BYTE_OFFS_LIMIT 0x7FFFUL 987 988 /* The data size of record must be smaller than this because we reserve 989 two upmost bits in a two byte offset for special purposes */ 990 #define REC_MAX_DATA_SIZE (16 * 1024) 991 992 #ifdef WITH_WSREP 993 dberr_t wsrep_rec_get_foreign_key( 994 byte *buf, /* out: extracted key */ 995 ulint *buf_len, /* in/out: length of buf */ 996 const rec_t* rec, /* in: physical record */ 997 dict_index_t* index_for, /* in: index for foreign table */ 998 dict_index_t* index_ref, /* in: index for referenced table */ 999 ibool new_protocol); /* in: protocol > 1 */ 1000 #endif /* WITH_WSREP */ 1001 #ifndef UNIV_NONINL 1002 #include "rem0rec.ic" 1003 #endif 1004 1005 #endif 1006