diff options
author | Guilhem Bichot <guilhem@mysql.com> | 2009-08-04 13:25:19 +0200 |
---|---|---|
committer | Guilhem Bichot <guilhem@mysql.com> | 2009-08-04 13:25:19 +0200 |
commit | b57e4dbd88671df86e2cf39aff5178976d710b64 (patch) | |
tree | 32be2bfec3ca062c65566c60ecf59b673d1f97e9 /storage/innobase/rem | |
parent | 1a0c2153a036296785dcdfa7b5f4974515616e11 (diff) | |
parent | 94efc1c6b084ed531b513e70fb66e7b7a1186b56 (diff) | |
download | mariadb-git-b57e4dbd88671df86e2cf39aff5178976d710b64.tar.gz |
Creation of mysql-trunk = {summit + "Innodb plugin replacing the builtin"}:
bzr branch mysql-5.1-performance-version mysql-trunk # Summit
cd mysql-trunk
bzr merge mysql-5.1-innodb_plugin # which is 5.1 + Innodb plugin
bzr rm innobase # remove the builtin
Next step: build, test fixes.
Diffstat (limited to 'storage/innobase/rem')
-rw-r--r-- | storage/innobase/rem/rem0cmp.c | 1064 | ||||
-rw-r--r-- | storage/innobase/rem/rem0rec.c | 1515 |
2 files changed, 0 insertions, 2579 deletions
diff --git a/storage/innobase/rem/rem0cmp.c b/storage/innobase/rem/rem0cmp.c deleted file mode 100644 index ca0ec663548..00000000000 --- a/storage/innobase/rem/rem0cmp.c +++ /dev/null @@ -1,1064 +0,0 @@ -/*********************************************************************** -Comparison services for records - -(c) 1994-1996 Innobase Oy - -Created 7/1/1994 Heikki Tuuri -************************************************************************/ - -#include "rem0cmp.h" - -#ifdef UNIV_NONINL -#include "rem0cmp.ic" -#endif - -#include "srv0srv.h" - -/* ALPHABETICAL ORDER - ================== - -The records are put into alphabetical order in the following -way: let F be the first field where two records disagree. -If there is a character in some position n where the the -records disagree, the order is determined by comparison of -the characters at position n, possibly after -collating transformation. If there is no such character, -but the corresponding fields have different lengths, then -if the data type of the fields is paddable, -shorter field is padded with a padding character. If the -data type is not paddable, longer field is considered greater. -Finally, the SQL null is bigger than any other value. - -At the present, the comparison functions return 0 in the case, -where two records disagree only in the way that one -has more fields than the other. */ - -#ifdef UNIV_DEBUG -/***************************************************************** -Used in debug checking of cmp_dtuple_... . -This function is used to compare a data tuple to a physical record. If -dtuple has n fields then rec must have either m >= n fields, or it must -differ from dtuple in some of the m fields rec has. */ -static -int -cmp_debug_dtuple_rec_with_match( -/*============================*/ - /* out: 1, 0, -1, if dtuple is greater, equal, - less than rec, respectively, when only the - common first fields are compared */ - dtuple_t* dtuple, /* in: data tuple */ - rec_t* rec, /* in: physical record which differs from - dtuple in some of the common fields, or which - has an equal number or more fields than - dtuple */ - const ulint* offsets,/* in: array returned by rec_get_offsets() */ - ulint* matched_fields);/* in/out: number of already - completely matched fields; when function - returns, contains the value for current - comparison */ -#endif /* UNIV_DEBUG */ -#ifndef UNIV_HOTBACKUP -/***************************************************************** -This function is used to compare two data fields for which the data type -is such that we must use MySQL code to compare them. The prototype here -must be a copy of the the one in ha_innobase.cc! */ -extern -int -innobase_mysql_cmp( -/*===============*/ - /* out: 1, 0, -1, if a is greater, - equal, less than b, respectively */ - int mysql_type, /* in: MySQL type */ - uint charset_number, /* in: number of the charset */ - unsigned char* a, /* in: data field */ - unsigned int a_length, /* in: data field length, - not UNIV_SQL_NULL */ - unsigned char* b, /* in: data field */ - unsigned int b_length); /* in: data field length, - not UNIV_SQL_NULL */ -#endif /* !UNIV_HOTBACKUP */ -/************************************************************************* -Transforms the character code so that it is ordered appropriately for the -language. This is only used for the latin1 char set. MySQL does the -comparisons for other char sets. */ -UNIV_INLINE -ulint -cmp_collate( -/*========*/ - /* out: collation order position */ - ulint code) /* in: code of a character stored in database record */ -{ - return((ulint) srv_latin1_ordering[code]); -} - -/***************************************************************** -Returns TRUE if two columns are equal for comparison purposes. */ - -ibool -cmp_cols_are_equal( -/*===============*/ - /* out: TRUE if the columns are - considered equal in comparisons */ - const dict_col_t* col1, /* in: column 1 */ - const dict_col_t* col2, /* in: column 2 */ - ibool check_charsets) - /* in: whether to check charsets */ -{ - if (dtype_is_non_binary_string_type(col1->mtype, col1->prtype) - && dtype_is_non_binary_string_type(col2->mtype, col2->prtype)) { - - /* Both are non-binary string types: they can be compared if - and only if the charset-collation is the same */ - - if (check_charsets) { - return(dtype_get_charset_coll(col1->prtype) - == dtype_get_charset_coll(col2->prtype)); - } else { - return(TRUE); - } - } - - if (dtype_is_binary_string_type(col1->mtype, col1->prtype) - && dtype_is_binary_string_type(col2->mtype, col2->prtype)) { - - /* Both are binary string types: they can be compared */ - - return(TRUE); - } - - if (col1->mtype != col2->mtype) { - - return(FALSE); - } - - if (col1->mtype == DATA_INT - && (col1->prtype & DATA_UNSIGNED) - != (col2->prtype & DATA_UNSIGNED)) { - - /* The storage format of an unsigned integer is different - from a signed integer: in a signed integer we OR - 0x8000... to the value of positive integers. */ - - return(FALSE); - } - - return(col1->mtype != DATA_INT || col1->len == col2->len); -} - -#ifndef UNIV_HOTBACKUP -/***************************************************************** -Innobase uses this function to compare two data fields for which the data type -is such that we must compare whole fields or call MySQL to do the comparison */ -static -int -cmp_whole_field( -/*============*/ - /* out: 1, 0, -1, if a is greater, - equal, less than b, respectively */ - ulint mtype, /* in: main type */ - ulint prtype, /* in: precise type */ - unsigned char* a, /* in: data field */ - unsigned int a_length, /* in: data field length, - not UNIV_SQL_NULL */ - unsigned char* b, /* in: data field */ - unsigned int b_length) /* in: data field length, - not UNIV_SQL_NULL */ -{ - float f_1; - float f_2; - double d_1; - double d_2; - int swap_flag = 1; - - switch (mtype) { - - case DATA_DECIMAL: - /* Remove preceding spaces */ - for (; a_length && *a == ' '; a++, a_length--); - for (; b_length && *b == ' '; b++, b_length--); - - if (*a == '-') { - if (*b != '-') { - return(-1); - } - - a++; b++; - a_length--; - b_length--; - - swap_flag = -1; - - } else if (*b == '-') { - - return(1); - } - - while (a_length > 0 && (*a == '+' || *a == '0')) { - a++; a_length--; - } - - while (b_length > 0 && (*b == '+' || *b == '0')) { - b++; b_length--; - } - - if (a_length != b_length) { - if (a_length < b_length) { - return(-swap_flag); - } - - return(swap_flag); - } - - while (a_length > 0 && *a == *b) { - - a++; b++; a_length--; - } - - if (a_length == 0) { - - return(0); - } - - if (*a > *b) { - return(swap_flag); - } - - return(-swap_flag); - case DATA_DOUBLE: - d_1 = mach_double_read(a); - d_2 = mach_double_read(b); - - if (d_1 > d_2) { - return(1); - } else if (d_2 > d_1) { - return(-1); - } - - return(0); - - case DATA_FLOAT: - f_1 = mach_float_read(a); - f_2 = mach_float_read(b); - - if (f_1 > f_2) { - return(1); - } else if (f_2 > f_1) { - return(-1); - } - - return(0); - case DATA_BLOB: - if (prtype & DATA_BINARY_TYPE) { - - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Error: comparing a binary BLOB" - " with a character set sensitive\n" - "InnoDB: comparison!\n"); - } - /* fall through */ - case DATA_VARMYSQL: - case DATA_MYSQL: - return(innobase_mysql_cmp( - (int)(prtype & DATA_MYSQL_TYPE_MASK), - (uint)dtype_get_charset_coll(prtype), - a, a_length, b, b_length)); - default: - fprintf(stderr, - "InnoDB: unknown type number %lu\n", - (ulong) mtype); - ut_error; - } - - return(0); -} -#endif /* !UNIV_HOTBACKUP */ - -/***************************************************************** -This function is used to compare two data fields for which we know the -data type. */ - -int -cmp_data_data_slow( -/*===============*/ - /* out: 1, 0, -1, if data1 is greater, equal, - less than data2, respectively */ - ulint mtype, /* in: main type */ - ulint prtype, /* in: precise type */ - byte* data1, /* in: data field (== a pointer to a memory - buffer) */ - ulint len1, /* in: data field length or UNIV_SQL_NULL */ - byte* data2, /* in: data field (== a pointer to a memory - buffer) */ - ulint len2) /* in: data field length or UNIV_SQL_NULL */ -{ -#ifndef UNIV_HOTBACKUP - ulint data1_byte; - ulint data2_byte; - ulint cur_bytes; - - if (len1 == UNIV_SQL_NULL || len2 == UNIV_SQL_NULL) { - - if (len1 == len2) { - - return(0); - } - - if (len1 == UNIV_SQL_NULL) { - /* We define the SQL null to be the smallest possible - value of a field in the alphabetical order */ - - return(-1); - } - - return(1); - } - - if (mtype >= DATA_FLOAT - || (mtype == DATA_BLOB - && 0 == (prtype & DATA_BINARY_TYPE) - && dtype_get_charset_coll(prtype) - != DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL)) { - - return(cmp_whole_field(mtype, prtype, - data1, (unsigned) len1, - data2, (unsigned) len2)); - } - - /* Compare then the fields */ - - cur_bytes = 0; - - for (;;) { - if (len1 <= cur_bytes) { - if (len2 <= cur_bytes) { - - return(0); - } - - data1_byte = dtype_get_pad_char(mtype, prtype); - - if (data1_byte == ULINT_UNDEFINED) { - - return(-1); - } - } else { - data1_byte = *data1; - } - - if (len2 <= cur_bytes) { - data2_byte = dtype_get_pad_char(mtype, prtype); - - if (data2_byte == ULINT_UNDEFINED) { - - return(1); - } - } else { - data2_byte = *data2; - } - - if (data1_byte == data2_byte) { - /* If the bytes are equal, they will remain such even - after the collation transformation below */ - - goto next_byte; - } - - if (mtype <= DATA_CHAR - || (mtype == DATA_BLOB - && 0 == (prtype & DATA_BINARY_TYPE))) { - - data1_byte = cmp_collate(data1_byte); - data2_byte = cmp_collate(data2_byte); - } - - if (data1_byte > data2_byte) { - - return(1); - } else if (data1_byte < data2_byte) { - - return(-1); - } -next_byte: - /* Next byte */ - cur_bytes++; - data1++; - data2++; - } -#else /* !UNIV_HOTBACKUP */ - /* This function depends on MySQL code that is not included in - InnoDB Hot Backup builds. Besides, this function should never - be called in InnoDB Hot Backup. */ - ut_error; -#endif /* !UNIV_HOTBACKUP */ - - return(0); /* Not reached */ -} - -/***************************************************************** -This function is used to compare a data tuple to a physical record. -Only dtuple->n_fields_cmp first fields are taken into account for -the the data tuple! If we denote by n = n_fields_cmp, then rec must -have either m >= n fields, or it must differ from dtuple in some of -the m fields rec has. If rec has an externally stored field we do not -compare it but return with value 0 if such a comparison should be -made. */ - -int -cmp_dtuple_rec_with_match( -/*======================*/ - /* out: 1, 0, -1, if dtuple is greater, equal, - less than rec, respectively, when only the - common first fields are compared, or - until the first externally stored field in - rec */ - dtuple_t* dtuple, /* in: data tuple */ - rec_t* rec, /* in: physical record which differs from - dtuple in some of the common fields, or which - has an equal number or more fields than - dtuple */ - const ulint* offsets,/* in: array returned by rec_get_offsets() */ - ulint* matched_fields, /* in/out: number of already completely - matched fields; when function returns, - contains the value for current comparison */ - ulint* matched_bytes) /* in/out: number of already matched - bytes within the first field not completely - matched; when function returns, contains the - value for current comparison */ -{ -#ifndef UNIV_HOTBACKUP - dfield_t* dtuple_field; /* current field in logical record */ - ulint dtuple_f_len; /* the length of the current field - in the logical record */ - byte* dtuple_b_ptr; /* pointer to the current byte in - logical field data */ - ulint dtuple_byte; /* value of current byte to be compared - in dtuple*/ - ulint rec_f_len; /* length of current field in rec */ - byte* rec_b_ptr; /* pointer to the current byte in - rec field */ - ulint rec_byte; /* value of current byte to be - compared in rec */ - ulint cur_field; /* current field number */ - ulint cur_bytes; /* number of already matched bytes - in current field */ - int ret = 3333; /* return value */ - - ut_ad(dtuple && rec && matched_fields && matched_bytes); - ut_ad(dtuple_check_typed(dtuple)); - ut_ad(rec_offs_validate(rec, NULL, offsets)); - - cur_field = *matched_fields; - cur_bytes = *matched_bytes; - - ut_ad(cur_field <= dtuple_get_n_fields_cmp(dtuple)); - ut_ad(cur_field <= rec_offs_n_fields(offsets)); - - if (cur_bytes == 0 && cur_field == 0) { - ulint rec_info = rec_get_info_bits(rec, - rec_offs_comp(offsets)); - ulint tup_info = dtuple_get_info_bits(dtuple); - - if (rec_info & REC_INFO_MIN_REC_FLAG) { - ret = !(tup_info & REC_INFO_MIN_REC_FLAG); - goto order_resolved; - } else if (tup_info & REC_INFO_MIN_REC_FLAG) { - ret = -1; - goto order_resolved; - } - } - - /* Match fields in a loop; stop if we run out of fields in dtuple - or find an externally stored field */ - - while (cur_field < dtuple_get_n_fields_cmp(dtuple)) { - - ulint mtype; - ulint prtype; - - dtuple_field = dtuple_get_nth_field(dtuple, cur_field); - { - const dtype_t* type - = dfield_get_type(dtuple_field); - - mtype = type->mtype; - prtype = type->prtype; - } - - dtuple_f_len = dfield_get_len(dtuple_field); - - rec_b_ptr = rec_get_nth_field(rec, offsets, - cur_field, &rec_f_len); - - /* If we have matched yet 0 bytes, it may be that one or - both the fields are SQL null, or the record or dtuple may be - the predefined minimum record, or the field is externally - stored */ - - if (UNIV_LIKELY(cur_bytes == 0)) { - if (rec_offs_nth_extern(offsets, cur_field)) { - /* We do not compare to an externally - stored field */ - - ret = 0; - - goto order_resolved; - } - - if (dtuple_f_len == UNIV_SQL_NULL) { - if (rec_f_len == UNIV_SQL_NULL) { - - goto next_field; - } - - ret = -1; - goto order_resolved; - } else if (rec_f_len == UNIV_SQL_NULL) { - /* We define the SQL null to be the - smallest possible value of a field - in the alphabetical order */ - - ret = 1; - goto order_resolved; - } - } - - if (mtype >= DATA_FLOAT - || (mtype == DATA_BLOB - && 0 == (prtype & DATA_BINARY_TYPE) - && dtype_get_charset_coll(prtype) - != DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL)) { - - ret = cmp_whole_field(mtype, prtype, - dfield_get_data(dtuple_field), - (unsigned) dtuple_f_len, - rec_b_ptr, (unsigned) rec_f_len); - - if (ret != 0) { - cur_bytes = 0; - - goto order_resolved; - } else { - goto next_field; - } - } - - /* Set the pointers at the current byte */ - - rec_b_ptr = rec_b_ptr + cur_bytes; - dtuple_b_ptr = (byte*)dfield_get_data(dtuple_field) - + cur_bytes; - /* Compare then the fields */ - - for (;;) { - if (UNIV_UNLIKELY(rec_f_len <= cur_bytes)) { - if (dtuple_f_len <= cur_bytes) { - - goto next_field; - } - - rec_byte = dtype_get_pad_char(mtype, prtype); - - if (rec_byte == ULINT_UNDEFINED) { - ret = 1; - - goto order_resolved; - } - } else { - rec_byte = *rec_b_ptr; - } - - if (UNIV_UNLIKELY(dtuple_f_len <= cur_bytes)) { - dtuple_byte = dtype_get_pad_char(mtype, - prtype); - - if (dtuple_byte == ULINT_UNDEFINED) { - ret = -1; - - goto order_resolved; - } - } else { - dtuple_byte = *dtuple_b_ptr; - } - - if (dtuple_byte == rec_byte) { - /* If the bytes are equal, they will - remain such even after the collation - transformation below */ - - goto next_byte; - } - - if (mtype <= DATA_CHAR - || (mtype == DATA_BLOB - && !(prtype & DATA_BINARY_TYPE))) { - - rec_byte = cmp_collate(rec_byte); - dtuple_byte = cmp_collate(dtuple_byte); - } - - ret = (int) (dtuple_byte - rec_byte); - if (UNIV_UNLIKELY(ret)) { - if (ret < 0) { - ret = -1; - goto order_resolved; - } else { - ret = 1; - goto order_resolved; - } - } -next_byte: - /* Next byte */ - cur_bytes++; - rec_b_ptr++; - dtuple_b_ptr++; - } - -next_field: - cur_field++; - cur_bytes = 0; - } - - ut_ad(cur_bytes == 0); - - ret = 0; /* If we ran out of fields, dtuple was equal to rec - up to the common fields */ -order_resolved: - ut_ad((ret >= - 1) && (ret <= 1)); - ut_ad(ret == cmp_debug_dtuple_rec_with_match(dtuple, rec, offsets, - matched_fields)); - ut_ad(*matched_fields == cur_field); /* In the debug version, the - above cmp_debug_... sets - *matched_fields to a value */ - *matched_fields = cur_field; - *matched_bytes = cur_bytes; - - return(ret); -#else /* !UNIV_HOTBACKUP */ - /* This function depends on MySQL code that is not included in - InnoDB Hot Backup builds. Besides, this function should never - be called in InnoDB Hot Backup. */ - ut_error; - return(0); -#endif /* !UNIV_HOTBACKUP */ -} - -/****************************************************************** -Compares a data tuple to a physical record. */ - -int -cmp_dtuple_rec( -/*===========*/ - /* out: 1, 0, -1, if dtuple is greater, equal, - less than rec, respectively; see the comments - for cmp_dtuple_rec_with_match */ - dtuple_t* dtuple, /* in: data tuple */ - rec_t* rec, /* in: physical record */ - const ulint* offsets)/* in: array returned by rec_get_offsets() */ -{ - ulint matched_fields = 0; - ulint matched_bytes = 0; - - ut_ad(rec_offs_validate(rec, NULL, offsets)); - return(cmp_dtuple_rec_with_match(dtuple, rec, offsets, - &matched_fields, &matched_bytes)); -} - -/****************************************************************** -Checks if a dtuple is a prefix of a record. The last field in dtuple -is allowed to be a prefix of the corresponding field in the record. */ - -ibool -cmp_dtuple_is_prefix_of_rec( -/*========================*/ - /* out: TRUE if prefix */ - dtuple_t* dtuple, /* in: data tuple */ - rec_t* rec, /* in: physical record */ - const ulint* offsets)/* in: array returned by rec_get_offsets() */ -{ - ulint n_fields; - ulint matched_fields = 0; - ulint matched_bytes = 0; - - ut_ad(rec_offs_validate(rec, NULL, offsets)); - n_fields = dtuple_get_n_fields(dtuple); - - if (n_fields > rec_offs_n_fields(offsets)) { - - return(FALSE); - } - - cmp_dtuple_rec_with_match(dtuple, rec, offsets, - &matched_fields, &matched_bytes); - if (matched_fields == n_fields) { - - return(TRUE); - } - - if (matched_fields == n_fields - 1 - && matched_bytes == dfield_get_len( - dtuple_get_nth_field(dtuple, n_fields - 1))) { - return(TRUE); - } - - return(FALSE); -} - -/***************************************************************** -This function is used to compare two physical records. Only the common -first fields are compared, and if an externally stored field is -encountered, then 0 is returned. */ - -int -cmp_rec_rec_with_match( -/*===================*/ - /* out: 1, 0 , -1 if rec1 is greater, equal, - less, respectively, than rec2; only the common - first fields are compared */ - rec_t* rec1, /* in: physical record */ - rec_t* rec2, /* in: physical record */ - const ulint* offsets1,/* in: rec_get_offsets(rec1, index) */ - const ulint* offsets2,/* in: rec_get_offsets(rec2, index) */ - dict_index_t* index, /* in: data dictionary index */ - ulint* matched_fields, /* in/out: number of already completely - matched fields; when the function returns, - contains the value the for current - comparison */ - ulint* matched_bytes) /* in/out: number of already matched - bytes within the first field not completely - matched; when the function returns, contains - the value for the current comparison */ -{ -#ifndef UNIV_HOTBACKUP - ulint rec1_n_fields; /* the number of fields in rec */ - ulint rec1_f_len; /* length of current field in rec */ - byte* rec1_b_ptr; /* pointer to the current byte in rec field */ - ulint rec1_byte; /* value of current byte to be compared in - rec */ - ulint rec2_n_fields; /* the number of fields in rec */ - ulint rec2_f_len; /* length of current field in rec */ - byte* rec2_b_ptr; /* pointer to the current byte in rec field */ - ulint rec2_byte; /* value of current byte to be compared in - rec */ - ulint cur_field; /* current field number */ - ulint cur_bytes; /* number of already matched bytes in current - field */ - int ret = 3333; /* return value */ - ulint comp; - - ut_ad(rec1 && rec2 && index); - ut_ad(rec_offs_validate(rec1, index, offsets1)); - ut_ad(rec_offs_validate(rec2, index, offsets2)); - ut_ad(rec_offs_comp(offsets1) == rec_offs_comp(offsets2)); - - comp = rec_offs_comp(offsets1); - rec1_n_fields = rec_offs_n_fields(offsets1); - rec2_n_fields = rec_offs_n_fields(offsets2); - - cur_field = *matched_fields; - cur_bytes = *matched_bytes; - - /* Match fields in a loop */ - - while ((cur_field < rec1_n_fields) && (cur_field < rec2_n_fields)) { - - ulint mtype; - ulint prtype; - - if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) { - /* This is for the insert buffer B-tree. */ - mtype = DATA_BINARY; - prtype = 0; - } else { - const dict_col_t* col - = dict_index_get_nth_col(index, cur_field); - - mtype = col->mtype; - prtype = col->prtype; - } - - rec1_b_ptr = rec_get_nth_field(rec1, offsets1, - cur_field, &rec1_f_len); - rec2_b_ptr = rec_get_nth_field(rec2, offsets2, - cur_field, &rec2_f_len); - - if (cur_bytes == 0) { - if (cur_field == 0) { - /* Test if rec is the predefined minimum - record */ - if (rec_get_info_bits(rec1, comp) - & REC_INFO_MIN_REC_FLAG) { - - if (rec_get_info_bits(rec2, comp) - & REC_INFO_MIN_REC_FLAG) { - ret = 0; - } else { - ret = -1; - } - - goto order_resolved; - - } else if (rec_get_info_bits(rec2, comp) - & REC_INFO_MIN_REC_FLAG) { - - ret = 1; - - goto order_resolved; - } - } - - if (rec_offs_nth_extern(offsets1, cur_field) - || rec_offs_nth_extern(offsets2, cur_field)) { - /* We do not compare to an externally - stored field */ - - ret = 0; - - goto order_resolved; - } - - if (rec1_f_len == UNIV_SQL_NULL - || rec2_f_len == UNIV_SQL_NULL) { - - if (rec1_f_len == rec2_f_len) { - - goto next_field; - - } else if (rec2_f_len == UNIV_SQL_NULL) { - - /* We define the SQL null to be the - smallest possible value of a field - in the alphabetical order */ - - ret = 1; - } else { - ret = -1; - } - - goto order_resolved; - } - } - - if (mtype >= DATA_FLOAT - || (mtype == DATA_BLOB - && 0 == (prtype & DATA_BINARY_TYPE) - && dtype_get_charset_coll(prtype) - != DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL)) { - - ret = cmp_whole_field(mtype, prtype, - rec1_b_ptr, - (unsigned) rec1_f_len, - rec2_b_ptr, - (unsigned) rec2_f_len); - if (ret != 0) { - cur_bytes = 0; - - goto order_resolved; - } else { - goto next_field; - } - } - - /* Set the pointers at the current byte */ - rec1_b_ptr = rec1_b_ptr + cur_bytes; - rec2_b_ptr = rec2_b_ptr + cur_bytes; - - /* Compare then the fields */ - for (;;) { - if (rec2_f_len <= cur_bytes) { - - if (rec1_f_len <= cur_bytes) { - - goto next_field; - } - - rec2_byte = dtype_get_pad_char(mtype, prtype); - - if (rec2_byte == ULINT_UNDEFINED) { - ret = 1; - - goto order_resolved; - } - } else { - rec2_byte = *rec2_b_ptr; - } - - if (rec1_f_len <= cur_bytes) { - rec1_byte = dtype_get_pad_char(mtype, prtype); - - if (rec1_byte == ULINT_UNDEFINED) { - ret = -1; - - goto order_resolved; - } - } else { - rec1_byte = *rec1_b_ptr; - } - - if (rec1_byte == rec2_byte) { - /* If the bytes are equal, they will remain - such even after the collation transformation - below */ - - goto next_byte; - } - - if (mtype <= DATA_CHAR - || (mtype == DATA_BLOB - && !(prtype & DATA_BINARY_TYPE))) { - - rec1_byte = cmp_collate(rec1_byte); - rec2_byte = cmp_collate(rec2_byte); - } - - if (rec1_byte < rec2_byte) { - ret = -1; - goto order_resolved; - } else if (rec1_byte > rec2_byte) { - ret = 1; - goto order_resolved; - } -next_byte: - /* Next byte */ - - cur_bytes++; - rec1_b_ptr++; - rec2_b_ptr++; - } - -next_field: - cur_field++; - cur_bytes = 0; - } - - ut_ad(cur_bytes == 0); - - ret = 0; /* If we ran out of fields, rec1 was equal to rec2 up - to the common fields */ -order_resolved: - - ut_ad((ret >= - 1) && (ret <= 1)); - - *matched_fields = cur_field; - *matched_bytes = cur_bytes; - - return(ret); -#else /* !UNIV_HOTBACKUP */ - /* This function depends on MySQL code that is not included in - InnoDB Hot Backup builds. Besides, this function should never - be called in InnoDB Hot Backup. */ - ut_error; - return(0); -#endif /* !UNIV_HOTBACKUP */ -} - -#ifdef UNIV_DEBUG -/***************************************************************** -Used in debug checking of cmp_dtuple_... . -This function is used to compare a data tuple to a physical record. If -dtuple has n fields then rec must have either m >= n fields, or it must -differ from dtuple in some of the m fields rec has. If encounters an -externally stored field, returns 0. */ -static -int -cmp_debug_dtuple_rec_with_match( -/*============================*/ - /* out: 1, 0, -1, if dtuple is greater, equal, - less than rec, respectively, when only the - common first fields are compared */ - dtuple_t* dtuple, /* in: data tuple */ - rec_t* rec, /* in: physical record which differs from - dtuple in some of the common fields, or which - has an equal number or more fields than - dtuple */ - const ulint* offsets,/* in: array returned by rec_get_offsets() */ - ulint* matched_fields) /* in/out: number of already - completely matched fields; when function - returns, contains the value for current - comparison */ -{ - dfield_t* dtuple_field; /* current field in logical record */ - ulint dtuple_f_len; /* the length of the current field - in the logical record */ - byte* dtuple_f_data; /* pointer to the current logical - field data */ - ulint rec_f_len; /* length of current field in rec */ - byte* rec_f_data; /* pointer to the current rec field */ - int ret = 3333; /* return value */ - ulint cur_field; /* current field number */ - - ut_ad(dtuple && rec && matched_fields); - ut_ad(dtuple_check_typed(dtuple)); - ut_ad(rec_offs_validate(rec, NULL, offsets)); - - ut_ad(*matched_fields <= dtuple_get_n_fields_cmp(dtuple)); - ut_ad(*matched_fields <= rec_offs_n_fields(offsets)); - - cur_field = *matched_fields; - - if (cur_field == 0) { - if (rec_get_info_bits(rec, rec_offs_comp(offsets)) - & REC_INFO_MIN_REC_FLAG) { - - ret = !(dtuple_get_info_bits(dtuple) - & REC_INFO_MIN_REC_FLAG); - - goto order_resolved; - } - - if (dtuple_get_info_bits(dtuple) & REC_INFO_MIN_REC_FLAG) { - ret = -1; - - goto order_resolved; - } - } - - /* Match fields in a loop; stop if we run out of fields in dtuple */ - - while (cur_field < dtuple_get_n_fields_cmp(dtuple)) { - - ulint mtype; - ulint prtype; - - dtuple_field = dtuple_get_nth_field(dtuple, cur_field); - { - const dtype_t* type - = dfield_get_type(dtuple_field); - - mtype = type->mtype; - prtype = type->prtype; - } - - dtuple_f_data = dfield_get_data(dtuple_field); - dtuple_f_len = dfield_get_len(dtuple_field); - - rec_f_data = rec_get_nth_field(rec, offsets, - cur_field, &rec_f_len); - - if (rec_offs_nth_extern(offsets, cur_field)) { - /* We do not compare to an externally stored field */ - - ret = 0; - - goto order_resolved; - } - - ret = cmp_data_data(mtype, prtype, dtuple_f_data, dtuple_f_len, - rec_f_data, rec_f_len); - if (ret != 0) { - goto order_resolved; - } - - cur_field++; - } - - ret = 0; /* If we ran out of fields, dtuple was equal to rec - up to the common fields */ -order_resolved: - ut_ad((ret >= - 1) && (ret <= 1)); - - *matched_fields = cur_field; - - return(ret); -} -#endif /* UNIV_DEBUG */ diff --git a/storage/innobase/rem/rem0rec.c b/storage/innobase/rem/rem0rec.c deleted file mode 100644 index 64f8e2d319c..00000000000 --- a/storage/innobase/rem/rem0rec.c +++ /dev/null @@ -1,1515 +0,0 @@ -/************************************************************************ -Record manager - -(c) 1994-2001 Innobase Oy - -Created 5/30/1994 Heikki Tuuri -*************************************************************************/ - -#include "rem0rec.h" - -#ifdef UNIV_NONINL -#include "rem0rec.ic" -#endif - -#include "mtr0mtr.h" -#include "mtr0log.h" - -/* PHYSICAL RECORD (OLD STYLE) - =========================== - -The physical record, which is the data type of all the records -found in index pages of the database, has the following format -(lower addresses and more significant bits inside a byte are below -represented on a higher text line): - -| offset of the end of the last field of data, the most significant - bit is set to 1 if and only if the field is SQL-null, - if the offset is 2-byte, then the second most significant - bit is set to 1 if the field is stored on another page: - mostly this will occur in the case of big BLOB fields | -... -| offset of the end of the first field of data + the SQL-null bit | -| 4 bits used to delete mark a record, and mark a predefined - minimum record in alphabetical order | -| 4 bits giving the number of records owned by this record - (this term is explained in page0page.h) | -| 13 bits giving the order number of this record in the - heap of the index page | -| 10 bits giving the number of fields in this record | -| 1 bit which is set to 1 if the offsets above are given in - one byte format, 0 if in two byte format | -| two bytes giving an absolute pointer to the next record in the page | -ORIGIN of the record -| first field of data | -... -| last field of data | - -The origin of the record is the start address of the first field -of data. The offsets are given relative to the origin. -The offsets of the data fields are stored in an inverted -order because then the offset of the first fields are near the -origin, giving maybe a better processor cache hit rate in searches. - -The offsets of the data fields are given as one-byte -(if there are less than 127 bytes of data in the record) -or two-byte unsigned integers. The most significant bit -is not part of the offset, instead it indicates the SQL-null -if the bit is set to 1. */ - -/* PHYSICAL RECORD (NEW STYLE) - =========================== - -The physical record, which is the data type of all the records -found in index pages of the database, has the following format -(lower addresses and more significant bits inside a byte are below -represented on a higher text line): - -| length of the last non-null variable-length field of data: - if the maximum length is 255, one byte; otherwise, - 0xxxxxxx (one byte, length=0..127), or 1exxxxxxxxxxxxxx (two bytes, - length=128..16383, extern storage flag) | -... -| length of first variable-length field of data | -| SQL-null flags (1 bit per nullable field), padded to full bytes | -| 4 bits used to delete mark a record, and mark a predefined - minimum record in alphabetical order | -| 4 bits giving the number of records owned by this record - (this term is explained in page0page.h) | -| 13 bits giving the order number of this record in the - heap of the index page | -| 3 bits record type: 000=conventional, 001=node pointer (inside B-tree), - 010=infimum, 011=supremum, 1xx=reserved | -| two bytes giving a relative pointer to the next record in the page | -ORIGIN of the record -| first field of data | -... -| last field of data | - -The origin of the record is the start address of the first field -of data. The offsets are given relative to the origin. -The offsets of the data fields are stored in an inverted -order because then the offset of the first fields are near the -origin, giving maybe a better processor cache hit rate in searches. - -The offsets of the data fields are given as one-byte -(if there are less than 127 bytes of data in the record) -or two-byte unsigned integers. The most significant bit -is not part of the offset, instead it indicates the SQL-null -if the bit is set to 1. */ - -/* CANONICAL COORDINATES. A record can be seen as a single -string of 'characters' in the following way: catenate the bytes -in each field, in the order of fields. An SQL-null field -is taken to be an empty sequence of bytes. Then after -the position of each field insert in the string -the 'character' <FIELD-END>, except that after an SQL-null field -insert <NULL-FIELD-END>. Now the ordinal position of each -byte in this canonical string is its canonical coordinate. -So, for the record ("AA", SQL-NULL, "BB", ""), the canonical -string is "AA<FIELD_END><NULL-FIELD-END>BB<FIELD-END><FIELD-END>". -We identify prefixes (= initial segments) of a record -with prefixes of the canonical string. The canonical -length of the prefix is the length of the corresponding -prefix of the canonical string. The canonical length of -a record is the length of its canonical string. - -For example, the maximal common prefix of records -("AA", SQL-NULL, "BB", "C") and ("AA", SQL-NULL, "B", "C") -is "AA<FIELD-END><NULL-FIELD-END>B", and its canonical -length is 5. - -A complete-field prefix of a record is a prefix which ends at the -end of some field (containing also <FIELD-END>). -A record is a complete-field prefix of another record, if -the corresponding canonical strings have the same property. */ - -ulint rec_dummy; /* this is used to fool compiler in - rec_validate */ - -/******************************************************************* -Validates the consistency of an old-style physical record. */ -static -ibool -rec_validate_old( -/*=============*/ - /* out: TRUE if ok */ - rec_t* rec); /* in: physical record */ - -/********************************************************** -The following function determines the offsets to each field in the -record. The offsets are written to a previously allocated array of -ulint, where rec_offs_n_fields(offsets) has been initialized to the -number of fields in the record. The rest of the array will be -initialized by this function. rec_offs_base(offsets)[0] will be set -to the extra size (if REC_OFFS_COMPACT is set, the record is in the -new format), and rec_offs_base(offsets)[1..n_fields] will be set to -offsets past the end of fields 0..n_fields, or to the beginning of -fields 1..n_fields+1. When the high-order bit of the offset at [i+1] -is set (REC_OFFS_SQL_NULL), the field i is NULL. When the second -high-order bit of the offset at [i+1] is set (REC_OFFS_EXTERNAL), the -field i is being stored externally. */ -static -void -rec_init_offsets( -/*=============*/ - rec_t* rec, /* in: physical record */ - dict_index_t* index, /* in: record descriptor */ - ulint* offsets)/* in/out: array of offsets; - in: n=rec_offs_n_fields(offsets) */ -{ - ulint i = 0; - ulint offs; - - rec_offs_make_valid(rec, index, offsets); - - if (dict_table_is_comp(index->table)) { - const byte* nulls; - const byte* lens; - dict_field_t* field; - ulint null_mask; - ulint status = rec_get_status(rec); - ulint n_node_ptr_field = ULINT_UNDEFINED; - - switch (UNIV_EXPECT(status, REC_STATUS_ORDINARY)) { - case REC_STATUS_INFIMUM: - case REC_STATUS_SUPREMUM: - /* the field is 8 bytes long */ - rec_offs_base(offsets)[0] - = REC_N_NEW_EXTRA_BYTES | REC_OFFS_COMPACT; - rec_offs_base(offsets)[1] = 8; - return; - case REC_STATUS_NODE_PTR: - n_node_ptr_field - = dict_index_get_n_unique_in_tree(index); - break; - case REC_STATUS_ORDINARY: - break; - } - - nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1); - lens = nulls - UT_BITS_IN_BYTES(index->n_nullable); - offs = 0; - null_mask = 1; - - /* read the lengths of fields 0..n */ - do { - ulint len; - if (UNIV_UNLIKELY(i == n_node_ptr_field)) { - len = offs += 4; - goto resolved; - } - - field = dict_index_get_nth_field(index, i); - if (!(dict_field_get_col(field)->prtype - & DATA_NOT_NULL)) { - /* nullable field => read the null flag */ - - if (UNIV_UNLIKELY(!(byte) null_mask)) { - nulls--; - null_mask = 1; - } - - if (*nulls & null_mask) { - null_mask <<= 1; - /* No length is stored for NULL fields. - We do not advance offs, and we set - the length to zero and enable the - SQL NULL flag in offsets[]. */ - len = offs | REC_OFFS_SQL_NULL; - goto resolved; - } - null_mask <<= 1; - } - - if (UNIV_UNLIKELY(!field->fixed_len)) { - /* Variable-length field: read the length */ - const dict_col_t* col - = dict_field_get_col(field); - len = *lens--; - if (UNIV_UNLIKELY(col->len > 255) - || UNIV_UNLIKELY(col->mtype - == DATA_BLOB)) { - if (len & 0x80) { - /* 1exxxxxxx xxxxxxxx */ - len <<= 8; - len |= *lens--; - - offs += len & 0x3fff; - if (UNIV_UNLIKELY(len - & 0x4000)) { - len = offs - | REC_OFFS_EXTERNAL; - } else { - len = offs; - } - - goto resolved; - } - } - - len = offs += len; - } else { - len = offs += field->fixed_len; - } -resolved: - rec_offs_base(offsets)[i + 1] = len; - } while (++i < rec_offs_n_fields(offsets)); - - *rec_offs_base(offsets) - = (rec - (lens + 1)) | REC_OFFS_COMPACT; - } else { - /* Old-style record: determine extra size and end offsets */ - offs = REC_N_OLD_EXTRA_BYTES; - if (rec_get_1byte_offs_flag(rec)) { - offs += rec_offs_n_fields(offsets); - *rec_offs_base(offsets) = offs; - /* Determine offsets to fields */ - do { - offs = rec_1_get_field_end_info(rec, i); - if (offs & REC_1BYTE_SQL_NULL_MASK) { - offs &= ~REC_1BYTE_SQL_NULL_MASK; - offs |= REC_OFFS_SQL_NULL; - } - rec_offs_base(offsets)[1 + i] = offs; - } while (++i < rec_offs_n_fields(offsets)); - } else { - offs += 2 * rec_offs_n_fields(offsets); - *rec_offs_base(offsets) = offs; - /* Determine offsets to fields */ - do { - offs = rec_2_get_field_end_info(rec, i); - if (offs & REC_2BYTE_SQL_NULL_MASK) { - offs &= ~REC_2BYTE_SQL_NULL_MASK; - offs |= REC_OFFS_SQL_NULL; - } - if (offs & REC_2BYTE_EXTERN_MASK) { - offs &= ~REC_2BYTE_EXTERN_MASK; - offs |= REC_OFFS_EXTERNAL; - } - rec_offs_base(offsets)[1 + i] = offs; - } while (++i < rec_offs_n_fields(offsets)); - } - } -} - -/********************************************************** -The following function determines the offsets to each field -in the record. It can reuse a previously returned array. */ - -ulint* -rec_get_offsets_func( -/*=================*/ - /* out: the new offsets */ - rec_t* rec, /* in: physical record */ - dict_index_t* index, /* in: record descriptor */ - ulint* offsets,/* in/out: array consisting of offsets[0] - allocated elements, or an array from - rec_get_offsets(), or NULL */ - ulint n_fields,/* in: maximum number of initialized fields - (ULINT_UNDEFINED if all fields) */ - mem_heap_t** heap, /* in/out: memory heap */ - const char* file, /* in: file name where called */ - ulint line) /* in: line number where called */ -{ - ulint n; - ulint size; - - ut_ad(rec); - ut_ad(index); - ut_ad(heap); - - if (dict_table_is_comp(index->table)) { - switch (UNIV_EXPECT(rec_get_status(rec), - REC_STATUS_ORDINARY)) { - case REC_STATUS_ORDINARY: - n = dict_index_get_n_fields(index); - break; - case REC_STATUS_NODE_PTR: - n = dict_index_get_n_unique_in_tree(index) + 1; - break; - case REC_STATUS_INFIMUM: - case REC_STATUS_SUPREMUM: - /* infimum or supremum record */ - n = 1; - break; - default: - ut_error; - return(NULL); - } - } else { - n = rec_get_n_fields_old(rec); - } - - if (UNIV_UNLIKELY(n_fields < n)) { - n = n_fields; - } - - size = n + (1 + REC_OFFS_HEADER_SIZE); - - if (UNIV_UNLIKELY(!offsets) - || UNIV_UNLIKELY(rec_offs_get_n_alloc(offsets) < size)) { - if (!*heap) { - *heap = mem_heap_create_func(size * sizeof(ulint), - NULL, MEM_HEAP_DYNAMIC, - file, line); - } - offsets = mem_heap_alloc(*heap, size * sizeof(ulint)); - rec_offs_set_n_alloc(offsets, size); - } - - rec_offs_set_n_fields(offsets, n); - rec_init_offsets(rec, index, offsets); - return(offsets); -} - -/**************************************************************** -The following function is used to get a pointer to the nth -data field in an old-style record. */ - -byte* -rec_get_nth_field_old( -/*==================*/ - /* out: pointer to the field */ - rec_t* rec, /* in: record */ - ulint n, /* in: index of the field */ - ulint* len) /* out: length of the field; UNIV_SQL_NULL if SQL - null */ -{ - ulint os; - ulint next_os; - - ut_ad(rec && len); - ut_ad(n < rec_get_n_fields_old(rec)); - - if (n > REC_MAX_N_FIELDS) { - fprintf(stderr, "Error: trying to access field %lu in rec\n", - (ulong) n); - ut_error; - } - - if (rec == NULL) { - fputs("Error: rec is NULL pointer\n", stderr); - ut_error; - } - - if (rec_get_1byte_offs_flag(rec)) { - os = rec_1_get_field_start_offs(rec, n); - - next_os = rec_1_get_field_end_info(rec, n); - - if (next_os & REC_1BYTE_SQL_NULL_MASK) { - *len = UNIV_SQL_NULL; - - return(rec + os); - } - - next_os = next_os & ~REC_1BYTE_SQL_NULL_MASK; - } else { - os = rec_2_get_field_start_offs(rec, n); - - next_os = rec_2_get_field_end_info(rec, n); - - if (next_os & REC_2BYTE_SQL_NULL_MASK) { - *len = UNIV_SQL_NULL; - - return(rec + os); - } - - next_os = next_os & ~(REC_2BYTE_SQL_NULL_MASK - | REC_2BYTE_EXTERN_MASK); - } - - *len = next_os - os; - - ut_ad(*len < UNIV_PAGE_SIZE); - - return(rec + os); -} - -/************************************************************** -The following function returns the size of a data tuple when converted to -a new-style physical record. */ - -ulint -rec_get_converted_size_new( -/*=======================*/ - /* out: size */ - dict_index_t* index, /* in: record descriptor */ - dtuple_t* dtuple) /* in: data tuple */ -{ - ulint size = REC_N_NEW_EXTRA_BYTES - + UT_BITS_IN_BYTES(index->n_nullable); - ulint i; - ulint n_fields; - ut_ad(index && dtuple); - ut_ad(dict_table_is_comp(index->table)); - - switch (dtuple_get_info_bits(dtuple) & REC_NEW_STATUS_MASK) { - case REC_STATUS_ORDINARY: - n_fields = dict_index_get_n_fields(index); - ut_ad(n_fields == dtuple_get_n_fields(dtuple)); - break; - case REC_STATUS_NODE_PTR: - n_fields = dict_index_get_n_unique_in_tree(index); - ut_ad(n_fields + 1 == dtuple_get_n_fields(dtuple)); - ut_ad(dtuple_get_nth_field(dtuple, n_fields)->len == 4); - size += 4; /* child page number */ - break; - case REC_STATUS_INFIMUM: - case REC_STATUS_SUPREMUM: - /* infimum or supremum record, 8 data bytes */ - return(REC_N_NEW_EXTRA_BYTES + 8); - default: - ut_error; - return(ULINT_UNDEFINED); - } - - /* read the lengths of fields 0..n */ - for (i = 0; i < n_fields; i++) { - dict_field_t* field; - ulint len; - const dict_col_t* col; - - field = dict_index_get_nth_field(index, i); - len = dtuple_get_nth_field(dtuple, i)->len; - col = dict_field_get_col(field); - - ut_ad(dict_col_type_assert_equal( - col, dfield_get_type(dtuple_get_nth_field( - dtuple, i)))); - - if (len == UNIV_SQL_NULL) { - /* No length is stored for NULL fields. */ - ut_ad(!(col->prtype & DATA_NOT_NULL)); - continue; - } - - ut_ad(len <= col->len || col->mtype == DATA_BLOB); - - if (field->fixed_len) { - ut_ad(len == field->fixed_len); - /* dict_index_add_col() should guarantee this */ - ut_ad(!field->prefix_len - || field->fixed_len == field->prefix_len); - } else if (len < 128 - || (col->len < 256 && col->mtype != DATA_BLOB)) { - size++; - } else { - /* For variable-length columns, we look up the - maximum length from the column itself. If this - is a prefix index column shorter than 256 bytes, - this will waste one byte. */ - size += 2; - } - size += len; - } - - return(size); -} - -/*************************************************************** -Sets the value of the ith field SQL null bit of an old-style record. */ - -void -rec_set_nth_field_null_bit( -/*=======================*/ - rec_t* rec, /* in: record */ - ulint i, /* in: ith field */ - ibool val) /* in: value to set */ -{ - ulint info; - - if (rec_get_1byte_offs_flag(rec)) { - - info = rec_1_get_field_end_info(rec, i); - - if (val) { - info = info | REC_1BYTE_SQL_NULL_MASK; - } else { - info = info & ~REC_1BYTE_SQL_NULL_MASK; - } - - rec_1_set_field_end_info(rec, i, info); - - return; - } - - info = rec_2_get_field_end_info(rec, i); - - if (val) { - info = info | REC_2BYTE_SQL_NULL_MASK; - } else { - info = info & ~REC_2BYTE_SQL_NULL_MASK; - } - - rec_2_set_field_end_info(rec, i, info); -} - -/*************************************************************** -Sets the value of the ith field extern storage bit of an old-style record. */ - -void -rec_set_nth_field_extern_bit_old( -/*=============================*/ - rec_t* rec, /* in: old-style record */ - ulint i, /* in: ith field */ - ibool val, /* in: value to set */ - mtr_t* mtr) /* in: mtr holding an X-latch to the page where - rec is, or NULL; in the NULL case we do not - write to log about the change */ -{ - ulint info; - - ut_a(!rec_get_1byte_offs_flag(rec)); - ut_a(i < rec_get_n_fields_old(rec)); - - info = rec_2_get_field_end_info(rec, i); - - if (val) { - info = info | REC_2BYTE_EXTERN_MASK; - } else { - info = info & ~REC_2BYTE_EXTERN_MASK; - } - - if (mtr) { - mlog_write_ulint(rec - REC_N_OLD_EXTRA_BYTES - 2 * (i + 1), - info, MLOG_2BYTES, mtr); - } else { - rec_2_set_field_end_info(rec, i, info); - } -} - -/*************************************************************** -Sets the value of the ith field extern storage bit of a new-style record. */ - -void -rec_set_nth_field_extern_bit_new( -/*=============================*/ - rec_t* rec, /* in: record */ - dict_index_t* index, /* in: record descriptor */ - ulint ith, /* in: ith field */ - ibool val, /* in: value to set */ - mtr_t* mtr) /* in: mtr holding an X-latch to the page - where rec is, or NULL; in the NULL case - we do not write to log about the change */ -{ - byte* nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1); - byte* lens = nulls - UT_BITS_IN_BYTES(index->n_nullable); - ulint i; - ulint n_fields; - ulint null_mask = 1; - ut_ad(rec && index); - ut_ad(dict_table_is_comp(index->table)); - ut_ad(rec_get_status(rec) == REC_STATUS_ORDINARY); - - n_fields = dict_index_get_n_fields(index); - - ut_ad(ith < n_fields); - - /* read the lengths of fields 0..n */ - for (i = 0; i < n_fields; i++) { - const dict_field_t* field; - const dict_col_t* col; - - field = dict_index_get_nth_field(index, i); - col = dict_field_get_col(field); - - if (!(col->prtype & DATA_NOT_NULL)) { - if (UNIV_UNLIKELY(!(byte) null_mask)) { - nulls--; - null_mask = 1; - } - - if (*nulls & null_mask) { - null_mask <<= 1; - /* NULL fields cannot be external. */ - ut_ad(i != ith); - continue; - } - - null_mask <<= 1; - } - if (field->fixed_len) { - /* fixed-length fields cannot be external - (Fixed-length fields longer than - DICT_MAX_INDEX_COL_LEN will be treated as - variable-length ones in dict_index_add_col().) */ - ut_ad(i != ith); - continue; - } - lens--; - if (col->len > 255 || col->mtype == DATA_BLOB) { - ulint len = lens[1]; - if (len & 0x80) { /* 1exxxxxx: 2-byte length */ - if (i == ith) { - if (!val == !(len & 0x40)) { - return; /* no change */ - } - /* toggle the extern bit */ - len ^= 0x40; - if (mtr) { - mlog_write_ulint(lens + 1, - len, - MLOG_1BYTE, - mtr); - } else { - lens[1] = (byte) len; - } - return; - } - lens--; - } else { - /* short fields cannot be external */ - ut_ad(i != ith); - } - } else { - /* short fields cannot be external */ - ut_ad(i != ith); - } - } -} - -/*************************************************************** -Sets TRUE the extern storage bits of fields mentioned in an array. */ - -void -rec_set_field_extern_bits( -/*======================*/ - rec_t* rec, /* in: record */ - dict_index_t* index, /* in: record descriptor */ - const ulint* vec, /* in: array of field numbers */ - ulint n_fields,/* in: number of fields numbers */ - mtr_t* mtr) /* in: mtr holding an X-latch to the - page where rec is, or NULL; - in the NULL case we do not write - to log about the change */ -{ - ulint i; - - if (dict_table_is_comp(index->table)) { - for (i = 0; i < n_fields; i++) { - rec_set_nth_field_extern_bit_new(rec, index, vec[i], - TRUE, mtr); - } - } else { - for (i = 0; i < n_fields; i++) { - rec_set_nth_field_extern_bit_old(rec, vec[i], - TRUE, mtr); - } - } -} - -/*************************************************************** -Sets an old-style record field to SQL null. -The physical size of the field is not changed. */ - -void -rec_set_nth_field_sql_null( -/*=======================*/ - rec_t* rec, /* in: record */ - ulint n) /* in: index of the field */ -{ - ulint offset; - - offset = rec_get_field_start_offs(rec, n); - - data_write_sql_null(rec + offset, rec_get_nth_field_size(rec, n)); - - rec_set_nth_field_null_bit(rec, n, TRUE); -} - -/************************************************************* -Builds an old-style physical record out of a data tuple and -stores it beginning from the start of the given buffer. */ -static -rec_t* -rec_convert_dtuple_to_rec_old( -/*==========================*/ - /* out: pointer to the origin of - physical record */ - byte* buf, /* in: start address of the physical record */ - dtuple_t* dtuple)/* in: data tuple */ -{ - dfield_t* field; - ulint n_fields; - ulint data_size; - rec_t* rec; - ulint end_offset; - ulint ored_offset; - byte* data; - ulint len; - ulint i; - - ut_ad(buf && dtuple); - ut_ad(dtuple_validate(dtuple)); - ut_ad(dtuple_check_typed(dtuple)); - - n_fields = dtuple_get_n_fields(dtuple); - data_size = dtuple_get_data_size(dtuple); - - ut_ad(n_fields > 0); - - /* Calculate the offset of the origin in the physical record */ - - rec = buf + rec_get_converted_extra_size(data_size, n_fields); -#ifdef UNIV_DEBUG - /* Suppress Valgrind warnings of ut_ad() - in mach_write_to_1(), mach_write_to_2() et al. */ - memset(buf, 0xff, rec - buf + data_size); -#endif /* UNIV_DEBUG */ - /* Store the number of fields */ - rec_set_n_fields_old(rec, n_fields); - - /* Set the info bits of the record */ - rec_set_info_bits(rec, FALSE, - dtuple_get_info_bits(dtuple) & REC_INFO_BITS_MASK); - - /* Store the data and the offsets */ - - end_offset = 0; - - if (data_size <= REC_1BYTE_OFFS_LIMIT) { - - rec_set_1byte_offs_flag(rec, TRUE); - - for (i = 0; i < n_fields; i++) { - - field = dtuple_get_nth_field(dtuple, i); - - data = dfield_get_data(field); - len = dfield_get_len(field); - - if (len == UNIV_SQL_NULL) { - len = dtype_get_sql_null_size( - dfield_get_type(field)); - data_write_sql_null(rec + end_offset, len); - - end_offset += len; - ored_offset = end_offset - | REC_1BYTE_SQL_NULL_MASK; - } else { - /* If the data is not SQL null, store it */ - ut_memcpy(rec + end_offset, data, len); - - end_offset += len; - ored_offset = end_offset; - } - - rec_1_set_field_end_info(rec, i, ored_offset); - } - } else { - rec_set_1byte_offs_flag(rec, FALSE); - - for (i = 0; i < n_fields; i++) { - - field = dtuple_get_nth_field(dtuple, i); - - data = dfield_get_data(field); - len = dfield_get_len(field); - - if (len == UNIV_SQL_NULL) { - len = dtype_get_sql_null_size( - dfield_get_type(field)); - data_write_sql_null(rec + end_offset, len); - - end_offset += len; - ored_offset = end_offset - | REC_2BYTE_SQL_NULL_MASK; - } else { - /* If the data is not SQL null, store it */ - ut_memcpy(rec + end_offset, data, len); - - end_offset += len; - ored_offset = end_offset; - } - - rec_2_set_field_end_info(rec, i, ored_offset); - } - } - - return(rec); -} - -/************************************************************* -Builds a new-style physical record out of a data tuple and -stores it beginning from the start of the given buffer. */ -static -rec_t* -rec_convert_dtuple_to_rec_new( -/*==========================*/ - /* out: pointer to the origin - of physical record */ - byte* buf, /* in: start address of the physical record */ - dict_index_t* index, /* in: record descriptor */ - dtuple_t* dtuple) /* in: data tuple */ -{ - dfield_t* field; - dtype_t* type; - rec_t* rec = buf + REC_N_NEW_EXTRA_BYTES; - byte* end; - byte* nulls; - byte* lens; - ulint len; - ulint i; - ulint n_node_ptr_field; - ulint fixed_len; - ulint null_mask = 1; - const ulint n_fields = dtuple_get_n_fields(dtuple); - const ulint status = dtuple_get_info_bits(dtuple) - & REC_NEW_STATUS_MASK; - ut_ad(dict_table_is_comp(index->table)); - ut_ad(n_fields > 0); - - /* Try to ensure that the memset() between the for() loops - completes fast. The address is not exact, but UNIV_PREFETCH - should never generate a memory fault. */ - UNIV_PREFETCH_RW(rec - REC_N_NEW_EXTRA_BYTES - n_fields); - UNIV_PREFETCH_RW(rec); - - switch (UNIV_EXPECT(status, REC_STATUS_ORDINARY)) { - case REC_STATUS_ORDINARY: - ut_ad(n_fields <= dict_index_get_n_fields(index)); - n_node_ptr_field = ULINT_UNDEFINED; - break; - case REC_STATUS_NODE_PTR: - ut_ad(n_fields == dict_index_get_n_unique_in_tree(index) + 1); - n_node_ptr_field = n_fields - 1; - break; - case REC_STATUS_INFIMUM: - case REC_STATUS_SUPREMUM: - ut_ad(n_fields == 1); - n_node_ptr_field = ULINT_UNDEFINED; - goto init; - default: - ut_a(0); - return(0); - } - - /* Calculate the offset of the origin in the physical record. - We must loop over all fields to do this. */ - rec += UT_BITS_IN_BYTES(index->n_nullable); - - for (i = 0; i < n_fields; i++) { - if (UNIV_UNLIKELY(i == n_node_ptr_field)) { -#ifdef UNIV_DEBUG - field = dtuple_get_nth_field(dtuple, i); - type = dfield_get_type(field); - ut_ad(dtype_get_prtype(type) & DATA_NOT_NULL); - ut_ad(dfield_get_len(field) == 4); -#endif /* UNIV_DEBUG */ - goto init; - } - field = dtuple_get_nth_field(dtuple, i); - type = dfield_get_type(field); - len = dfield_get_len(field); - fixed_len = dict_index_get_nth_field(index, i)->fixed_len; - - ut_ad(dict_col_type_assert_equal( - dict_field_get_col(dict_index_get_nth_field( - index, i)), - dfield_get_type(field))); - - if (!(dtype_get_prtype(type) & DATA_NOT_NULL)) { - if (len == UNIV_SQL_NULL) - continue; - } - /* only nullable fields can be null */ - ut_ad(len != UNIV_SQL_NULL); - if (fixed_len) { - ut_ad(len == fixed_len); - } else { - ut_ad(len <= dtype_get_len(type) - || dtype_get_mtype(type) == DATA_BLOB); - rec++; - if (len >= 128 - && (dtype_get_len(type) >= 256 - || dtype_get_mtype(type) == DATA_BLOB)) { - rec++; - } - } - } - -init: - end = rec; - nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1); - lens = nulls - UT_BITS_IN_BYTES(index->n_nullable); - /* clear the SQL-null flags */ - memset (lens + 1, 0, nulls - lens); - - /* Set the info bits of the record */ - rec_set_status(rec, status); - - rec_set_info_bits(rec, TRUE, - dtuple_get_info_bits(dtuple) & REC_INFO_BITS_MASK); - - /* Store the data and the offsets */ - - for (i = 0; i < n_fields; i++) { - field = dtuple_get_nth_field(dtuple, i); - type = dfield_get_type(field); - len = dfield_get_len(field); - - if (UNIV_UNLIKELY(i == n_node_ptr_field)) { - ut_ad(dtype_get_prtype(type) & DATA_NOT_NULL); - ut_ad(len == 4); - memcpy(end, dfield_get_data(field), len); - break; - } - fixed_len = dict_index_get_nth_field(index, i)->fixed_len; - - if (!(dtype_get_prtype(type) & DATA_NOT_NULL)) { - /* nullable field */ - ut_ad(index->n_nullable > 0); - - if (UNIV_UNLIKELY(!(byte) null_mask)) { - nulls--; - null_mask = 1; - } - - ut_ad(*nulls < null_mask); - - /* set the null flag if necessary */ - if (len == UNIV_SQL_NULL) { - *nulls |= null_mask; - null_mask <<= 1; - continue; - } - - null_mask <<= 1; - } - /* only nullable fields can be null */ - ut_ad(len != UNIV_SQL_NULL); - if (fixed_len) { - ut_ad(len == fixed_len); - } else { - ut_ad(len <= dtype_get_len(type) - || dtype_get_mtype(type) == DATA_BLOB); - if (len < 128 - || (dtype_get_len(type) < 256 - && dtype_get_mtype(type) != DATA_BLOB)) { - - *lens-- = (byte) len; - } else { - /* the extern bits will be set later */ - ut_ad(len < 16384); - *lens-- = (byte) (len >> 8) | 0x80; - *lens-- = (byte) len; - } - } - - memcpy(end, dfield_get_data(field), len); - end += len; - } - - return(rec); -} - -/************************************************************* -Builds a physical record out of a data tuple and -stores it beginning from the start of the given buffer. */ - -rec_t* -rec_convert_dtuple_to_rec( -/*======================*/ - /* out: pointer to the origin - of physical record */ - byte* buf, /* in: start address of the - physical record */ - dict_index_t* index, /* in: record descriptor */ - dtuple_t* dtuple) /* in: data tuple */ -{ - rec_t* rec; - - ut_ad(buf && index && dtuple); - ut_ad(dtuple_validate(dtuple)); - ut_ad(dtuple_check_typed(dtuple)); - - if (dict_table_is_comp(index->table)) { - rec = rec_convert_dtuple_to_rec_new(buf, index, dtuple); - } else { - rec = rec_convert_dtuple_to_rec_old(buf, dtuple); - } - -#ifdef UNIV_DEBUG - { - mem_heap_t* heap = NULL; - ulint offsets_[REC_OFFS_NORMAL_SIZE]; - const ulint* offsets; - *offsets_ = (sizeof offsets_) / sizeof *offsets_; - - offsets = rec_get_offsets(rec, index, - offsets_, ULINT_UNDEFINED, &heap); - ut_ad(rec_validate(rec, offsets)); - if (UNIV_LIKELY_NULL(heap)) { - mem_heap_free(heap); - } - } -#endif /* UNIV_DEBUG */ - return(rec); -} - -/****************************************************************** -Copies the first n fields of a physical record to a data tuple. The fields -are copied to the memory heap. */ - -void -rec_copy_prefix_to_dtuple( -/*======================*/ - dtuple_t* tuple, /* in: data tuple */ - rec_t* rec, /* in: physical record */ - dict_index_t* index, /* in: record descriptor */ - ulint n_fields, /* in: number of fields to copy */ - mem_heap_t* heap) /* in: memory heap */ -{ - dfield_t* field; - byte* data; - ulint len; - byte* buf = NULL; - ulint i; - ulint offsets_[REC_OFFS_NORMAL_SIZE]; - ulint* offsets = offsets_; - *offsets_ = (sizeof offsets_) / sizeof *offsets_; - - offsets = rec_get_offsets(rec, index, offsets, n_fields, &heap); - - ut_ad(rec_validate(rec, offsets)); - ut_ad(dtuple_check_typed(tuple)); - - dtuple_set_info_bits(tuple, rec_get_info_bits( - rec, dict_table_is_comp(index->table))); - - for (i = 0; i < n_fields; i++) { - - field = dtuple_get_nth_field(tuple, i); - data = rec_get_nth_field(rec, offsets, i, &len); - - if (len != UNIV_SQL_NULL) { - buf = mem_heap_alloc(heap, len); - - ut_memcpy(buf, data, len); - } - - dfield_set_data(field, buf, len); - } -} - -/****************************************************************** -Copies the first n fields of an old-style physical record -to a new physical record in a buffer. */ -static -rec_t* -rec_copy_prefix_to_buf_old( -/*=======================*/ - /* out, own: copied record */ - rec_t* rec, /* in: physical record */ - ulint n_fields, /* in: number of fields to copy */ - ulint area_end, /* in: end of the prefix data */ - byte** buf, /* in/out: memory buffer for the copied prefix, - or NULL */ - ulint* buf_size) /* in/out: buffer size */ -{ - rec_t* copy_rec; - ulint area_start; - ulint prefix_len; - - if (rec_get_1byte_offs_flag(rec)) { - area_start = REC_N_OLD_EXTRA_BYTES + n_fields; - } else { - area_start = REC_N_OLD_EXTRA_BYTES + 2 * n_fields; - } - - prefix_len = area_start + area_end; - - if ((*buf == NULL) || (*buf_size < prefix_len)) { - if (*buf != NULL) { - mem_free(*buf); - } - - *buf = mem_alloc(prefix_len); - *buf_size = prefix_len; - } - - ut_memcpy(*buf, rec - area_start, prefix_len); - - copy_rec = *buf + area_start; - - rec_set_n_fields_old(copy_rec, n_fields); - - return(copy_rec); -} - -/****************************************************************** -Copies the first n fields of a physical record to a new physical record in -a buffer. */ - -rec_t* -rec_copy_prefix_to_buf( -/*===================*/ - /* out, own: copied record */ - rec_t* rec, /* in: physical record */ - dict_index_t* index, /* in: record descriptor */ - ulint n_fields, /* in: number of fields to copy */ - byte** buf, /* in/out: memory buffer - for the copied prefix, or NULL */ - ulint* buf_size) /* in/out: buffer size */ -{ - byte* nulls; - byte* lens; - ulint i; - ulint prefix_len; - ulint null_mask; - ulint status; - - UNIV_PREFETCH_RW(*buf); - - if (!dict_table_is_comp(index->table)) { - ut_ad(rec_validate_old(rec)); - return(rec_copy_prefix_to_buf_old( - rec, n_fields, - rec_get_field_start_offs(rec, n_fields), - buf, buf_size)); - } - - status = rec_get_status(rec); - - switch (status) { - case REC_STATUS_ORDINARY: - ut_ad(n_fields <= dict_index_get_n_fields(index)); - break; - case REC_STATUS_NODE_PTR: - /* it doesn't make sense to copy the child page number field */ - ut_ad(n_fields <= dict_index_get_n_unique_in_tree(index)); - break; - case REC_STATUS_INFIMUM: - case REC_STATUS_SUPREMUM: - /* infimum or supremum record: no sense to copy anything */ - default: - ut_error; - return(NULL); - } - - nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1); - lens = nulls - UT_BITS_IN_BYTES(index->n_nullable); - UNIV_PREFETCH_R(lens); - prefix_len = 0; - null_mask = 1; - - /* read the lengths of fields 0..n */ - for (i = 0; i < n_fields; i++) { - const dict_field_t* field; - const dict_col_t* col; - - field = dict_index_get_nth_field(index, i); - col = dict_field_get_col(field); - - if (!(col->prtype & DATA_NOT_NULL)) { - /* nullable field => read the null flag */ - if (UNIV_UNLIKELY(!(byte) null_mask)) { - nulls--; - null_mask = 1; - } - - if (*nulls & null_mask) { - null_mask <<= 1; - continue; - } - - null_mask <<= 1; - } - - if (field->fixed_len) { - prefix_len += field->fixed_len; - } else { - ulint len = *lens--; - if (col->len > 255 || col->mtype == DATA_BLOB) { - if (len & 0x80) { - /* 1exxxxxx */ - len &= 0x3f; - len <<= 8; - len |= *lens--; - UNIV_PREFETCH_R(lens); - } - } - prefix_len += len; - } - } - - UNIV_PREFETCH_R(rec + prefix_len); - - prefix_len += rec - (lens + 1); - - if ((*buf == NULL) || (*buf_size < prefix_len)) { - if (*buf != NULL) { - mem_free(*buf); - } - - *buf = mem_alloc(prefix_len); - *buf_size = prefix_len; - } - - memcpy(*buf, lens + 1, prefix_len); - - return(*buf + (rec - (lens + 1))); -} - -/******************************************************************* -Validates the consistency of an old-style physical record. */ -static -ibool -rec_validate_old( -/*=============*/ - /* out: TRUE if ok */ - rec_t* rec) /* in: physical record */ -{ - byte* data; - ulint len; - ulint n_fields; - ulint len_sum = 0; - ulint sum = 0; - ulint i; - - ut_a(rec); - n_fields = rec_get_n_fields_old(rec); - - if ((n_fields == 0) || (n_fields > REC_MAX_N_FIELDS)) { - fprintf(stderr, "InnoDB: Error: record has %lu fields\n", - (ulong) n_fields); - return(FALSE); - } - - for (i = 0; i < n_fields; i++) { - data = rec_get_nth_field_old(rec, i, &len); - - if (!((len < UNIV_PAGE_SIZE) || (len == UNIV_SQL_NULL))) { - fprintf(stderr, - "InnoDB: Error: record field %lu len %lu\n", - (ulong) i, - (ulong) len); - return(FALSE); - } - - if (len != UNIV_SQL_NULL) { - len_sum += len; - sum += *(data + len -1); /* dereference the - end of the field to - cause a memory trap - if possible */ - } else { - len_sum += rec_get_nth_field_size(rec, i); - } - } - - if (len_sum != rec_get_data_size_old(rec)) { - fprintf(stderr, - "InnoDB: Error: record len should be %lu, len %lu\n", - (ulong) len_sum, - rec_get_data_size_old(rec)); - return(FALSE); - } - - rec_dummy = sum; /* This is here only to fool the compiler */ - - return(TRUE); -} - -/******************************************************************* -Validates the consistency of a physical record. */ - -ibool -rec_validate( -/*=========*/ - /* out: TRUE if ok */ - rec_t* rec, /* in: physical record */ - const ulint* offsets)/* in: array returned by rec_get_offsets() */ -{ - const byte* data; - ulint len; - ulint n_fields; - ulint len_sum = 0; - ulint sum = 0; - ulint i; - - ut_a(rec); - n_fields = rec_offs_n_fields(offsets); - - if ((n_fields == 0) || (n_fields > REC_MAX_N_FIELDS)) { - fprintf(stderr, "InnoDB: Error: record has %lu fields\n", - (ulong) n_fields); - return(FALSE); - } - - ut_a(rec_offs_comp(offsets) || n_fields <= rec_get_n_fields_old(rec)); - - for (i = 0; i < n_fields; i++) { - data = rec_get_nth_field(rec, offsets, i, &len); - - if (!((len < UNIV_PAGE_SIZE) || (len == UNIV_SQL_NULL))) { - fprintf(stderr, - "InnoDB: Error: record field %lu len %lu\n", - (ulong) i, - (ulong) len); - return(FALSE); - } - - if (len != UNIV_SQL_NULL) { - len_sum += len; - sum += *(data + len -1); /* dereference the - end of the field to - cause a memory trap - if possible */ - } else if (!rec_offs_comp(offsets)) { - len_sum += rec_get_nth_field_size(rec, i); - } - } - - if (len_sum != (ulint)(rec_get_end(rec, offsets) - rec)) { - fprintf(stderr, - "InnoDB: Error: record len should be %lu, len %lu\n", - (ulong) len_sum, - (ulong) (rec_get_end(rec, offsets) - rec)); - return(FALSE); - } - - rec_dummy = sum; /* This is here only to fool the compiler */ - - if (!rec_offs_comp(offsets)) { - ut_a(rec_validate_old(rec)); - } - - return(TRUE); -} - -/******************************************************************* -Prints an old-style physical record. */ - -void -rec_print_old( -/*==========*/ - FILE* file, /* in: file where to print */ - rec_t* rec) /* in: physical record */ -{ - const byte* data; - ulint len; - ulint n; - ulint i; - - ut_ad(rec); - - n = rec_get_n_fields_old(rec); - - fprintf(file, "PHYSICAL RECORD: n_fields %lu;" - " %u-byte offsets; info bits %lu\n", - (ulong) n, - rec_get_1byte_offs_flag(rec) ? 1 : 2, - (ulong) rec_get_info_bits(rec, FALSE)); - - for (i = 0; i < n; i++) { - - data = rec_get_nth_field_old(rec, i, &len); - - fprintf(file, " %lu:", (ulong) i); - - if (len != UNIV_SQL_NULL) { - if (len <= 30) { - - ut_print_buf(file, data, len); - } else { - ut_print_buf(file, data, 30); - - fputs("...(truncated)", file); - } - } else { - fprintf(file, " SQL NULL, size %lu ", - rec_get_nth_field_size(rec, i)); - } - putc(';', file); - } - - putc('\n', file); - - rec_validate_old(rec); -} - -/******************************************************************* -Prints a physical record. */ - -void -rec_print_new( -/*==========*/ - FILE* file, /* in: file where to print */ - rec_t* rec, /* in: physical record */ - const ulint* offsets)/* in: array returned by rec_get_offsets() */ -{ - const byte* data; - ulint len; - ulint i; - - ut_ad(rec_offs_validate(rec, NULL, offsets)); - - if (!rec_offs_comp(offsets)) { - rec_print_old(file, rec); - return; - } - - ut_ad(rec); - - fprintf(file, "PHYSICAL RECORD: n_fields %lu;" - " compact format; info bits %lu\n", - (ulong) rec_offs_n_fields(offsets), - (ulong) rec_get_info_bits(rec, TRUE)); - - for (i = 0; i < rec_offs_n_fields(offsets); i++) { - - data = rec_get_nth_field(rec, offsets, i, &len); - - fprintf(file, " %lu:", (ulong) i); - - if (len != UNIV_SQL_NULL) { - if (len <= 30) { - - ut_print_buf(file, data, len); - } else { - ut_print_buf(file, data, 30); - - fputs("...(truncated)", file); - } - } else { - fputs(" SQL NULL", file); - } - putc(';', file); - } - - putc('\n', file); - - rec_validate(rec, offsets); -} - -/******************************************************************* -Prints a physical record. */ - -void -rec_print( -/*======*/ - FILE* file, /* in: file where to print */ - rec_t* rec, /* in: physical record */ - dict_index_t* index) /* in: record descriptor */ -{ - ut_ad(index); - - if (!dict_table_is_comp(index->table)) { - rec_print_old(file, rec); - return; - } else { - mem_heap_t* heap = NULL; - ulint offsets_[REC_OFFS_NORMAL_SIZE]; - *offsets_ = (sizeof offsets_) / sizeof *offsets_; - - rec_print_new(file, rec, - rec_get_offsets(rec, index, offsets_, - ULINT_UNDEFINED, &heap)); - if (UNIV_LIKELY_NULL(heap)) { - mem_heap_free(heap); - } - } -} |