1/***************************************************************************** 2 3Copyright (c) 1994, 2021, Oracle and/or its affiliates. 4 5This program is free software; you can redistribute it and/or modify 6it under the terms of the GNU General Public License, version 2.0, 7as published by the Free Software Foundation. 8 9This program is also distributed with certain software (including 10but not limited to OpenSSL) that is licensed under separate terms, 11as designated in a particular file or component or in included license 12documentation. The authors of MySQL hereby grant you an additional 13permission to link the program and your derivative works with the 14separately licensed software that they have included with MySQL. 15 16This program is distributed in the hope that it will be useful, 17but WITHOUT ANY WARRANTY; without even the implied warranty of 18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19GNU General Public License, version 2.0, for more details. 20 21You should have received a copy of the GNU General Public License along with 22this program; if not, write to the Free Software Foundation, Inc., 2351 Franklin Street, Suite 500, Boston, MA 02110-1335 USA 24 25*****************************************************************************/ 26 27/********************************************************************//** 28@file include/data0data.ic 29SQL data field and tuple 30 31Created 5/30/1994 Heikki Tuuri 32*************************************************************************/ 33 34#include "mem0mem.h" 35#include "ut0rnd.h" 36#include "btr0types.h" 37 38#ifdef UNIV_DEBUG 39/** Dummy variable to catch access to uninitialized fields. In the 40debug version, dtuple_create() will make all fields of dtuple_t point 41to data_error. */ 42extern byte data_error; 43 44/*********************************************************************//** 45Gets pointer to the type struct of SQL data field. 46@return pointer to the type struct */ 47UNIV_INLINE 48dtype_t* 49dfield_get_type( 50/*============*/ 51 const dfield_t* field) /*!< in: SQL data field */ 52{ 53 ut_ad(field); 54 55 return((dtype_t*) &(field->type)); 56} 57#endif /* UNIV_DEBUG */ 58 59/*********************************************************************//** 60Sets the type struct of SQL data field. */ 61UNIV_INLINE 62void 63dfield_set_type( 64/*============*/ 65 dfield_t* field, /*!< in: SQL data field */ 66 const dtype_t* type) /*!< in: pointer to data type struct */ 67{ 68 ut_ad(field != NULL); 69 ut_ad(type != NULL); 70 71 field->type = *type; 72} 73 74#ifdef UNIV_DEBUG 75/*********************************************************************//** 76Gets pointer to the data in a field. 77@return pointer to data */ 78UNIV_INLINE 79void* 80dfield_get_data( 81/*============*/ 82 const dfield_t* field) /*!< in: field */ 83{ 84 ut_ad(field); 85 ut_ad((field->len == UNIV_SQL_NULL) 86 || (field->data != &data_error)); 87 88 return((void*) field->data); 89} 90#endif /* UNIV_DEBUG */ 91 92/*********************************************************************//** 93Gets length of field data. 94@return length of data; UNIV_SQL_NULL if SQL null data */ 95UNIV_INLINE 96ulint 97dfield_get_len( 98/*===========*/ 99 const dfield_t* field) /*!< in: field */ 100{ 101 ut_ad(field); 102 ut_ad((field->len == UNIV_SQL_NULL) 103 || (field->data != &data_error)); 104 105 return(field->len); 106} 107 108/*********************************************************************//** 109Sets length in a field. */ 110UNIV_INLINE 111void 112dfield_set_len( 113/*===========*/ 114 dfield_t* field, /*!< in: field */ 115 ulint len) /*!< in: length or UNIV_SQL_NULL */ 116{ 117 ut_ad(field); 118#ifdef UNIV_VALGRIND_DEBUG 119 if (len != UNIV_SQL_NULL) UNIV_MEM_ASSERT_RW(field->data, len); 120#endif /* UNIV_VALGRIND_DEBUG */ 121 122 field->ext = 0; 123 field->len = static_cast<unsigned int>(len); 124} 125 126/*********************************************************************//** 127Determines if a field is SQL NULL 128@return nonzero if SQL null data */ 129UNIV_INLINE 130ulint 131dfield_is_null( 132/*===========*/ 133 const dfield_t* field) /*!< in: field */ 134{ 135 ut_ad(field); 136 137 return(field->len == UNIV_SQL_NULL); 138} 139 140/*********************************************************************//** 141Determines if a field is externally stored 142@return nonzero if externally stored */ 143UNIV_INLINE 144ulint 145dfield_is_ext( 146/*==========*/ 147 const dfield_t* field) /*!< in: field */ 148{ 149 ut_ad(field); 150 ut_ad(!field->ext || field->len >= BTR_EXTERN_FIELD_REF_SIZE); 151 152 return(field->ext); 153} 154 155/*********************************************************************//** 156Sets the "external storage" flag */ 157UNIV_INLINE 158void 159dfield_set_ext( 160/*===========*/ 161 dfield_t* field) /*!< in/out: field */ 162{ 163 ut_ad(field); 164 165 field->ext = 1; 166} 167 168/** Gets spatial status for "external storage" 169@param[in,out] field field */ 170UNIV_INLINE 171spatial_status_t 172dfield_get_spatial_status( 173 const dfield_t* field) 174{ 175 ut_ad(field); 176 ut_ad(dfield_is_ext(field)); 177 178 return(static_cast<spatial_status_t>(field->spatial_status)); 179} 180 181/** Sets spatial status for "external storage" 182@param[in,out] field field 183@param[in] spatial_status spatial status */ 184UNIV_INLINE 185void 186dfield_set_spatial_status( 187 dfield_t* field, 188 spatial_status_t spatial_status) 189{ 190 ut_ad(field); 191 ut_ad(dfield_is_ext(field)); 192 193 field->spatial_status = spatial_status; 194} 195 196/*********************************************************************//** 197Sets pointer to the data and length in a field. */ 198UNIV_INLINE 199void 200dfield_set_data( 201/*============*/ 202 dfield_t* field, /*!< in: field */ 203 const void* data, /*!< in: data */ 204 ulint len) /*!< in: length or UNIV_SQL_NULL */ 205{ 206 ut_ad(field); 207 208#ifdef UNIV_VALGRIND_DEBUG 209 if (len != UNIV_SQL_NULL) UNIV_MEM_ASSERT_RW(data, len); 210#endif /* UNIV_VALGRIND_DEBUG */ 211 field->data = (void*) data; 212 field->ext = 0; 213 field->len = static_cast<unsigned int>(len); 214} 215 216/*********************************************************************//** 217Sets pointer to the data and length in a field. */ 218UNIV_INLINE 219void 220dfield_write_mbr( 221/*=============*/ 222 dfield_t* field, /*!< in: field */ 223 const double* mbr) /*!< in: data */ 224{ 225 ut_ad(field); 226 227#ifdef UNIV_VALGRIND_DEBUG 228 if (len != UNIV_SQL_NULL) UNIV_MEM_ASSERT_RW(data, len); 229#endif /* UNIV_VALGRIND_DEBUG */ 230 field->ext = 0; 231 232 for (int i = 0; i < SPDIMS * 2; i++) { 233 mach_double_write(static_cast<byte*>(field->data) 234 + i * sizeof(double), mbr[i]); 235 } 236 237 field->len = DATA_MBR_LEN; 238} 239 240/*********************************************************************//** 241Sets a data field to SQL NULL. */ 242UNIV_INLINE 243void 244dfield_set_null( 245/*============*/ 246 dfield_t* field) /*!< in/out: field */ 247{ 248 dfield_set_data(field, NULL, UNIV_SQL_NULL); 249} 250 251/*********************************************************************//** 252Copies the data and len fields. */ 253UNIV_INLINE 254void 255dfield_copy_data( 256/*=============*/ 257 dfield_t* field1, /*!< out: field to copy to */ 258 const dfield_t* field2) /*!< in: field to copy from */ 259{ 260 ut_ad(field1 != NULL); 261 ut_ad(field2 != NULL); 262 263 field1->data = field2->data; 264 field1->len = field2->len; 265 field1->ext = field2->ext; 266 field1->spatial_status = field2->spatial_status; 267} 268 269/*********************************************************************//** 270Copies a data field to another. */ 271UNIV_INLINE 272void 273dfield_copy( 274/*========*/ 275 dfield_t* field1, /*!< out: field to copy to */ 276 const dfield_t* field2) /*!< in: field to copy from */ 277{ 278 *field1 = *field2; 279} 280 281/*********************************************************************//** 282Copies the data pointed to by a data field. */ 283UNIV_INLINE 284void 285dfield_dup( 286/*=======*/ 287 dfield_t* field, /*!< in/out: data field */ 288 mem_heap_t* heap) /*!< in: memory heap where allocated */ 289{ 290 if (!dfield_is_null(field)) { 291 UNIV_MEM_ASSERT_RW(field->data, field->len); 292 field->data = mem_heap_dup(heap, field->data, field->len); 293 } 294} 295 296#ifndef UNIV_HOTBACKUP 297/*********************************************************************//** 298Tests if two data fields are equal. 299If len==0, tests the data length and content for equality. 300If len>0, tests the first len bytes of the content for equality. 301@return TRUE if both fields are NULL or if they are equal */ 302UNIV_INLINE 303ibool 304dfield_datas_are_binary_equal( 305/*==========================*/ 306 const dfield_t* field1, /*!< in: field */ 307 const dfield_t* field2, /*!< in: field */ 308 ulint len) /*!< in: maximum prefix to compare, 309 or 0 to compare the whole field length */ 310{ 311 ulint len2 = len; 312 313 if (field1->len == UNIV_SQL_NULL || len == 0 || field1->len < len) { 314 len = field1->len; 315 } 316 317 if (field2->len == UNIV_SQL_NULL || len2 == 0 || field2->len < len2) { 318 len2 = field2->len; 319 } 320 321 return(len == len2 322 && (len == UNIV_SQL_NULL 323 || !memcmp(field1->data, field2->data, len))); 324} 325 326/*********************************************************************//** 327Tests if dfield data length and content is equal to the given. 328@return TRUE if equal */ 329UNIV_INLINE 330ibool 331dfield_data_is_binary_equal( 332/*========================*/ 333 const dfield_t* field, /*!< in: field */ 334 ulint len, /*!< in: data length or UNIV_SQL_NULL */ 335 const byte* data) /*!< in: data */ 336{ 337 return(len == dfield_get_len(field) 338 && (len == UNIV_SQL_NULL 339 || !memcmp(dfield_get_data(field), data, len))); 340} 341#endif /* !UNIV_HOTBACKUP */ 342 343/*********************************************************************//** 344Gets info bits in a data tuple. 345@return info bits */ 346UNIV_INLINE 347ulint 348dtuple_get_info_bits( 349/*=================*/ 350 const dtuple_t* tuple) /*!< in: tuple */ 351{ 352 ut_ad(tuple); 353 354 return(tuple->info_bits); 355} 356 357/*********************************************************************//** 358Sets info bits in a data tuple. */ 359UNIV_INLINE 360void 361dtuple_set_info_bits( 362/*=================*/ 363 dtuple_t* tuple, /*!< in: tuple */ 364 ulint info_bits) /*!< in: info bits */ 365{ 366 ut_ad(tuple); 367 368 tuple->info_bits = info_bits; 369} 370 371/*********************************************************************//** 372Gets number of fields used in record comparisons. 373@return number of fields used in comparisons in rem0cmp.* */ 374UNIV_INLINE 375ulint 376dtuple_get_n_fields_cmp( 377/*====================*/ 378 const dtuple_t* tuple) /*!< in: tuple */ 379{ 380 ut_ad(tuple); 381 382 return(tuple->n_fields_cmp); 383} 384 385/*********************************************************************//** 386Sets number of fields used in record comparisons. */ 387UNIV_INLINE 388void 389dtuple_set_n_fields_cmp( 390/*====================*/ 391 dtuple_t* tuple, /*!< in: tuple */ 392 ulint n_fields_cmp) /*!< in: number of fields used in 393 comparisons in rem0cmp.* */ 394{ 395 ut_ad(tuple); 396 ut_ad(n_fields_cmp <= tuple->n_fields); 397 398 tuple->n_fields_cmp = n_fields_cmp; 399} 400 401/*********************************************************************//** 402Gets number of fields in a data tuple. 403@return number of fields */ 404UNIV_INLINE 405ulint 406dtuple_get_n_fields( 407/*================*/ 408 const dtuple_t* tuple) /*!< in: tuple */ 409{ 410 ut_ad(tuple); 411 412 return(tuple->n_fields); 413} 414 415/** Gets the number of virtual fields in a data tuple. 416@param[in] tuple dtuple to check 417@return number of fields */ 418UNIV_INLINE 419ulint 420dtuple_get_n_v_fields( 421 const dtuple_t* tuple) 422{ 423 ut_ad(tuple); 424 425 return(tuple->n_v_fields); 426} 427#ifdef UNIV_DEBUG 428/** Gets nth field of a tuple. 429@param[in] tuple tuple 430@param[in] n index of field 431@return nth field */ 432UNIV_INLINE 433dfield_t* 434dtuple_get_nth_field( 435 const dtuple_t* tuple, 436 ulint n) 437{ 438 ut_ad(tuple); 439 ut_ad(n < tuple->n_fields); 440 441 return((dfield_t*) tuple->fields + n); 442} 443/** Gets nth virtual field of a tuple. 444@param[in] tuple tuple 445@oaran[in] n the nth field to get 446@return nth field */ 447UNIV_INLINE 448dfield_t* 449dtuple_get_nth_v_field( 450 const dtuple_t* tuple, 451 ulint n) 452{ 453 ut_ad(tuple); 454 ut_ad(n < tuple->n_v_fields); 455 456 return(static_cast<dfield_t*>(tuple->v_fields + n)); 457} 458#endif /* UNIV_DEBUG */ 459 460/** Creates a data tuple from an already allocated chunk of memory. 461The size of the chunk must be at least DTUPLE_EST_ALLOC(n_fields). 462The default value for number of fields used in record comparisons 463for this tuple is n_fields. 464@param[in,out] buf buffer to use 465@param[in] buf_size buffer size 466@param[in] n_fields number of field 467@param[in] n_v_fields number of fields on virtual columns 468@return created tuple (inside buf) */ 469UNIV_INLINE 470dtuple_t* 471dtuple_create_from_mem( 472 void* buf, 473 ulint buf_size, 474 ulint n_fields, 475 ulint n_v_fields) 476{ 477 dtuple_t* tuple; 478 ulint n_t_fields = n_fields + n_v_fields; 479 480 ut_ad(buf != NULL); 481 ut_a(buf_size >= DTUPLE_EST_ALLOC(n_t_fields)); 482 483 tuple = (dtuple_t*) buf; 484 tuple->info_bits = 0; 485 tuple->n_fields = n_fields; 486 tuple->n_v_fields = n_v_fields; 487 tuple->n_fields_cmp = n_fields; 488 tuple->fields = (dfield_t*) &tuple[1]; 489 if (n_v_fields > 0) { 490 tuple->v_fields = &tuple->fields[n_fields]; 491 } else { 492 tuple->v_fields = NULL; 493 } 494 495#ifdef UNIV_DEBUG 496 tuple->magic_n = DATA_TUPLE_MAGIC_N; 497 498 { /* In the debug version, initialize fields to an error value */ 499 ulint i; 500 501 for (i = 0; i < n_t_fields; i++) { 502 dfield_t* field; 503 504 if (i >= n_fields) { 505 field = dtuple_get_nth_v_field( 506 tuple, i - n_fields); 507 } else { 508 field = dtuple_get_nth_field(tuple, i); 509 } 510 511 dfield_set_len(field, UNIV_SQL_NULL); 512 field->data = &data_error; 513 dfield_get_type(field)->mtype = DATA_ERROR; 514 dfield_get_type(field)->prtype = DATA_ERROR; 515 } 516 } 517#endif 518 UNIV_MEM_ASSERT_W(tuple->fields, n_t_fields * sizeof *tuple->fields); 519 UNIV_MEM_INVALID(tuple->fields, n_t_fields * sizeof *tuple->fields); 520 return(tuple); 521} 522 523/** Duplicate the virtual field data in a dtuple_t 524@param[in,out] vrow dtuple contains the virtual fields 525@param[in] heap heap memory to use */ 526UNIV_INLINE 527void 528dtuple_dup_v_fld( 529 const dtuple_t* vrow, 530 mem_heap_t* heap) 531{ 532 for (ulint i = 0; i < vrow->n_v_fields; i++) { 533 dfield_t* dfield = dtuple_get_nth_v_field(vrow, i); 534 dfield_dup(dfield, heap); 535 } 536} 537 538/** Initialize the virtual field data in a dtuple_t 539@param[in,out] vrow dtuple contains the virtual fields */ 540UNIV_INLINE 541void 542dtuple_init_v_fld( 543 const dtuple_t* vrow) 544{ 545 for (ulint i = 0; i < vrow->n_v_fields; i++) { 546 dfield_t* dfield = dtuple_get_nth_v_field(vrow, i); 547 dfield_get_type(dfield)->mtype = DATA_MISSING; 548 dfield_set_len(dfield, UNIV_SQL_NULL); 549 } 550} 551 552/**********************************************************//** 553Creates a data tuple to a memory heap. The default value for number 554of fields used in record comparisons for this tuple is n_fields. 555@return own: created tuple */ 556UNIV_INLINE 557dtuple_t* 558dtuple_create( 559/*==========*/ 560 mem_heap_t* heap, /*!< in: memory heap where the tuple 561 is created, DTUPLE_EST_ALLOC(n_fields) 562 bytes will be allocated from this heap */ 563 ulint n_fields) /*!< in: number of fields */ 564{ 565 return(dtuple_create_with_vcol(heap, n_fields, 0)); 566} 567 568/** Creates a data tuple with virtual columns to a memory heap. 569@param[in] heap memory heap where the tuple is created 570@param[in] n_fields number of fields 571@param[in] n_v_fields number of fields on virtual col 572@return own: created tuple */ 573UNIV_INLINE 574dtuple_t* 575dtuple_create_with_vcol( 576 mem_heap_t* heap, 577 ulint n_fields, 578 ulint n_v_fields) 579{ 580 void* buf; 581 ulint buf_size; 582 dtuple_t* tuple; 583 584 ut_ad(heap); 585 586 buf_size = DTUPLE_EST_ALLOC(n_fields + n_v_fields); 587 buf = mem_heap_alloc(heap, buf_size); 588 589 tuple = dtuple_create_from_mem(buf, buf_size, n_fields, n_v_fields); 590 591#ifdef UNIV_DEBUG 592 tuple->m_heap = heap; 593#endif /* UNIV_DEBUG */ 594 return(tuple); 595} 596 597/** Copies a data tuple's virtual fields to another. This is a shallow copy; 598@param[in,out] d_tuple destination tuple 599@param[in] s_tuple source tuple */ 600UNIV_INLINE 601void 602dtuple_copy_v_fields( 603 dtuple_t* d_tuple, 604 const dtuple_t* s_tuple) 605{ 606 607 ulint n_v_fields = dtuple_get_n_v_fields(d_tuple); 608 ut_ad(n_v_fields == dtuple_get_n_v_fields(s_tuple)); 609 610 for (ulint i = 0; i < n_v_fields; i++) { 611 dfield_copy(dtuple_get_nth_v_field(d_tuple, i), 612 dtuple_get_nth_v_field(s_tuple, i)); 613 } 614} 615 616/*********************************************************************//** 617Copies a data tuple to another. This is a shallow copy; if a deep copy 618is desired, dfield_dup() will have to be invoked on each field. 619@return own: copy of tuple */ 620UNIV_INLINE 621dtuple_t* 622dtuple_copy( 623/*========*/ 624 const dtuple_t* tuple, /*!< in: tuple to copy from */ 625 mem_heap_t* heap) /*!< in: memory heap 626 where the tuple is created */ 627{ 628 ulint n_fields = dtuple_get_n_fields(tuple); 629 ulint n_v_fields = dtuple_get_n_v_fields(tuple); 630 dtuple_t* new_tuple = dtuple_create_with_vcol( 631 heap, n_fields, n_v_fields); 632 ulint i; 633 634 for (i = 0; i < n_fields; i++) { 635 dfield_copy(dtuple_get_nth_field(new_tuple, i), 636 dtuple_get_nth_field(tuple, i)); 637 } 638 639 for (i = 0; i < n_v_fields; i++) { 640 dfield_copy(dtuple_get_nth_v_field(new_tuple, i), 641 dtuple_get_nth_v_field(tuple, i)); 642 } 643 644 return(new_tuple); 645} 646 647/**********************************************************//** 648The following function returns the sum of data lengths of a tuple. The space 649occupied by the field structs or the tuple struct is not counted. Neither 650is possible space in externally stored parts of the field. 651@return sum of data lengths */ 652UNIV_INLINE 653ulint 654dtuple_get_data_size( 655/*=================*/ 656 const dtuple_t* tuple, /*!< in: typed data tuple */ 657 ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */ 658{ 659 const dfield_t* field; 660 ulint n_fields; 661 ulint len; 662 ulint i; 663 ulint sum = 0; 664 665 ut_ad(tuple); 666 ut_ad(dtuple_check_typed(tuple)); 667 ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N); 668 669 n_fields = tuple->n_fields; 670 671 for (i = 0; i < n_fields; i++) { 672 field = dtuple_get_nth_field(tuple, i); 673 len = dfield_get_len(field); 674 675 if (len == UNIV_SQL_NULL) { 676 len = dtype_get_sql_null_size(dfield_get_type(field), 677 comp); 678 } 679 680 sum += len; 681 } 682 683 return(sum); 684} 685 686/*********************************************************************//** 687Computes the number of externally stored fields in a data tuple. 688@return number of externally stored fields */ 689UNIV_INLINE 690ulint 691dtuple_get_n_ext( 692/*=============*/ 693 const dtuple_t* tuple) /*!< in: tuple */ 694{ 695 ulint n_ext = 0; 696 ulint n_fields = tuple->n_fields; 697 ulint i; 698 699 ut_ad(tuple); 700 ut_ad(dtuple_check_typed(tuple)); 701 ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N); 702 703 for (i = 0; i < n_fields; i++) { 704 n_ext += dtuple_get_nth_field(tuple, i)->ext; 705 } 706 707 return(n_ext); 708} 709 710/*******************************************************************//** 711Sets types of fields binary in a tuple. */ 712UNIV_INLINE 713void 714dtuple_set_types_binary( 715/*====================*/ 716 dtuple_t* tuple, /*!< in: data tuple */ 717 ulint n) /*!< in: number of fields to set */ 718{ 719 dtype_t* dfield_type; 720 ulint i; 721 722 for (i = 0; i < n; i++) { 723 dfield_type = dfield_get_type(dtuple_get_nth_field(tuple, i)); 724 dtype_set(dfield_type, DATA_BINARY, 0, 0); 725 } 726} 727 728/** Fold a prefix given as the number of fields of a tuple. 729@param[in] tuple index record 730@param[in] n_fields number of complete fields to fold 731@param[in] n_bytes number of bytes to fold in the last field 732@param[in] index_id index tree ID 733@return the folded value */ 734UNIV_INLINE 735ulint 736dtuple_fold( 737 const dtuple_t* tuple, 738 ulint n_fields, 739 ulint n_bytes, 740 index_id_t tree_id) 741{ 742 const dfield_t* field; 743 ulint i; 744 const byte* data; 745 ulint len; 746 ulint fold; 747 748 ut_ad(tuple); 749 ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N); 750 ut_ad(dtuple_check_typed(tuple)); 751 752 fold = ut_fold_ull(tree_id); 753 754 for (i = 0; i < n_fields; i++) { 755 field = dtuple_get_nth_field(tuple, i); 756 757 data = (const byte*) dfield_get_data(field); 758 len = dfield_get_len(field); 759 760 if (len != UNIV_SQL_NULL) { 761 fold = ut_fold_ulint_pair(fold, 762 ut_fold_binary(data, len)); 763 } 764 } 765 766 if (n_bytes > 0) { 767 field = dtuple_get_nth_field(tuple, i); 768 769 data = (const byte*) dfield_get_data(field); 770 len = dfield_get_len(field); 771 772 if (len != UNIV_SQL_NULL) { 773 if (len > n_bytes) { 774 len = n_bytes; 775 } 776 777 fold = ut_fold_ulint_pair(fold, 778 ut_fold_binary(data, len)); 779 } 780 } 781 782 return(fold); 783} 784 785/**********************************************************************//** 786Writes an SQL null field full of zeros. */ 787UNIV_INLINE 788void 789data_write_sql_null( 790/*================*/ 791 byte* data, /*!< in: pointer to a buffer of size len */ 792 ulint len) /*!< in: SQL null size in bytes */ 793{ 794 memset(data, 0, len); 795} 796 797/**********************************************************************//** 798Checks if a dtuple contains an SQL null value. 799@return TRUE if some field is SQL null */ 800UNIV_INLINE 801ibool 802dtuple_contains_null( 803/*=================*/ 804 const dtuple_t* tuple) /*!< in: dtuple */ 805{ 806 ulint n; 807 ulint i; 808 809 n = dtuple_get_n_fields(tuple); 810 811 for (i = 0; i < n; i++) { 812 if (dfield_is_null(dtuple_get_nth_field(tuple, i))) { 813 814 return(TRUE); 815 } 816 } 817 818 return(FALSE); 819} 820 821/**************************************************************//** 822Frees the memory in a big rec vector. */ 823UNIV_INLINE 824void 825dtuple_big_rec_free( 826/*================*/ 827 big_rec_t* vector) /*!< in, own: big rec vector; it is 828 freed in this function */ 829{ 830 mem_heap_free(vector->heap); 831} 832