diff options
Diffstat (limited to 'storage/xtradb/include/rem0rec.ic')
-rw-r--r-- | storage/xtradb/include/rem0rec.ic | 1719 |
1 files changed, 0 insertions, 1719 deletions
diff --git a/storage/xtradb/include/rem0rec.ic b/storage/xtradb/include/rem0rec.ic deleted file mode 100644 index 5811a77a48b..00000000000 --- a/storage/xtradb/include/rem0rec.ic +++ /dev/null @@ -1,1719 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free Software -Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA - -*****************************************************************************/ - -/********************************************************************//** -@file include/rem0rec.ic -Record manager - -Created 5/30/1994 Heikki Tuuri -*************************************************************************/ - -#include "mach0data.h" -#include "ut0byte.h" -#include "dict0dict.h" -#include "btr0types.h" - -/* Compact flag ORed to the extra size returned by rec_get_offsets() */ -#define REC_OFFS_COMPACT ((ulint) 1 << 31) -/* SQL NULL flag in offsets returned by rec_get_offsets() */ -#define REC_OFFS_SQL_NULL ((ulint) 1 << 31) -/* External flag in offsets returned by rec_get_offsets() */ -#define REC_OFFS_EXTERNAL ((ulint) 1 << 30) -/* Mask for offsets returned by rec_get_offsets() */ -#define REC_OFFS_MASK (REC_OFFS_EXTERNAL - 1) - -/* Offsets of the bit-fields in an old-style record. NOTE! In the table the -most significant bytes and bits are written below less significant. - - (1) byte offset (2) bit usage within byte - downward from - origin -> 1 8 bits pointer to next record - 2 8 bits pointer to next record - 3 1 bit short flag - 7 bits number of fields - 4 3 bits number of fields - 5 bits heap number - 5 8 bits heap number - 6 4 bits n_owned - 4 bits info bits -*/ - -/* Offsets of the bit-fields in a new-style record. NOTE! In the table the -most significant bytes and bits are written below less significant. - - (1) byte offset (2) bit usage within byte - downward from - origin -> 1 8 bits relative offset of next record - 2 8 bits relative offset of next record - the relative offset is an unsigned 16-bit - integer: - (offset_of_next_record - - offset_of_this_record) mod 64Ki, - where mod is the modulo as a non-negative - number; - we can calculate the offset of the next - record with the formula: - relative_offset + offset_of_this_record - mod UNIV_PAGE_SIZE - 3 3 bits status: - 000=conventional record - 001=node pointer record (inside B-tree) - 010=infimum record - 011=supremum record - 1xx=reserved - 5 bits heap number - 4 8 bits heap number - 5 4 bits n_owned - 4 bits info bits -*/ - -/* We list the byte offsets from the origin of the record, the mask, -and the shift needed to obtain each bit-field of the record. */ - -#define REC_NEXT 2 -#define REC_NEXT_MASK 0xFFFFUL -#define REC_NEXT_SHIFT 0 - -#define REC_OLD_SHORT 3 /* This is single byte bit-field */ -#define REC_OLD_SHORT_MASK 0x1UL -#define REC_OLD_SHORT_SHIFT 0 - -#define REC_OLD_N_FIELDS 4 -#define REC_OLD_N_FIELDS_MASK 0x7FEUL -#define REC_OLD_N_FIELDS_SHIFT 1 - -#define REC_NEW_STATUS 3 /* This is single byte bit-field */ -#define REC_NEW_STATUS_MASK 0x7UL -#define REC_NEW_STATUS_SHIFT 0 - -#define REC_OLD_HEAP_NO 5 -#define REC_HEAP_NO_MASK 0xFFF8UL -#if 0 /* defined in rem0rec.h for use of page0zip.cc */ -#define REC_NEW_HEAP_NO 4 -#define REC_HEAP_NO_SHIFT 3 -#endif - -#define REC_OLD_N_OWNED 6 /* This is single byte bit-field */ -#define REC_NEW_N_OWNED 5 /* This is single byte bit-field */ -#define REC_N_OWNED_MASK 0xFUL -#define REC_N_OWNED_SHIFT 0 - -#define REC_OLD_INFO_BITS 6 /* This is single byte bit-field */ -#define REC_NEW_INFO_BITS 5 /* This is single byte bit-field */ -#define REC_INFO_BITS_MASK 0xF0UL -#define REC_INFO_BITS_SHIFT 0 - -#if REC_OLD_SHORT_MASK << (8 * (REC_OLD_SHORT - 3)) \ - ^ REC_OLD_N_FIELDS_MASK << (8 * (REC_OLD_N_FIELDS - 4)) \ - ^ REC_HEAP_NO_MASK << (8 * (REC_OLD_HEAP_NO - 4)) \ - ^ REC_N_OWNED_MASK << (8 * (REC_OLD_N_OWNED - 3)) \ - ^ REC_INFO_BITS_MASK << (8 * (REC_OLD_INFO_BITS - 3)) \ - ^ 0xFFFFFFFFUL -# error "sum of old-style masks != 0xFFFFFFFFUL" -#endif -#if REC_NEW_STATUS_MASK << (8 * (REC_NEW_STATUS - 3)) \ - ^ REC_HEAP_NO_MASK << (8 * (REC_NEW_HEAP_NO - 4)) \ - ^ REC_N_OWNED_MASK << (8 * (REC_NEW_N_OWNED - 3)) \ - ^ REC_INFO_BITS_MASK << (8 * (REC_NEW_INFO_BITS - 3)) \ - ^ 0xFFFFFFUL -# error "sum of new-style masks != 0xFFFFFFUL" -#endif - -/***********************************************************//** -Sets the value of the ith field SQL null bit of an old-style record. */ -UNIV_INTERN -void -rec_set_nth_field_null_bit( -/*=======================*/ - rec_t* rec, /*!< in: record */ - ulint i, /*!< in: ith field */ - ibool val); /*!< in: value to set */ -/***********************************************************//** -Sets an old-style record field to SQL null. -The physical size of the field is not changed. */ -UNIV_INTERN -void -rec_set_nth_field_sql_null( -/*=======================*/ - rec_t* rec, /*!< in: record */ - ulint n); /*!< in: index of the field */ - -/******************************************************//** -Gets a bit field from within 1 byte. */ -UNIV_INLINE -ulint -rec_get_bit_field_1( -/*================*/ - const rec_t* rec, /*!< in: pointer to record origin */ - ulint offs, /*!< in: offset from the origin down */ - ulint mask, /*!< in: mask used to filter bits */ - ulint shift) /*!< in: shift right applied after masking */ -{ - ut_ad(rec); - - return((mach_read_from_1(rec - offs) & mask) >> shift); -} - -/******************************************************//** -Sets a bit field within 1 byte. */ -UNIV_INLINE -void -rec_set_bit_field_1( -/*================*/ - rec_t* rec, /*!< in: pointer to record origin */ - ulint val, /*!< in: value to set */ - ulint offs, /*!< in: offset from the origin down */ - ulint mask, /*!< in: mask used to filter bits */ - ulint shift) /*!< in: shift right applied after masking */ -{ - ut_ad(rec); - ut_ad(offs <= REC_N_OLD_EXTRA_BYTES); - ut_ad(mask); - ut_ad(mask <= 0xFFUL); - ut_ad(((mask >> shift) << shift) == mask); - ut_ad(((val << shift) & mask) == (val << shift)); - - mach_write_to_1(rec - offs, - (mach_read_from_1(rec - offs) & ~mask) - | (val << shift)); -} - -/******************************************************//** -Gets a bit field from within 2 bytes. */ -UNIV_INLINE -ulint -rec_get_bit_field_2( -/*================*/ - const rec_t* rec, /*!< in: pointer to record origin */ - ulint offs, /*!< in: offset from the origin down */ - ulint mask, /*!< in: mask used to filter bits */ - ulint shift) /*!< in: shift right applied after masking */ -{ - ut_ad(rec); - - return((mach_read_from_2(rec - offs) & mask) >> shift); -} - -/******************************************************//** -Sets a bit field within 2 bytes. */ -UNIV_INLINE -void -rec_set_bit_field_2( -/*================*/ - rec_t* rec, /*!< in: pointer to record origin */ - ulint val, /*!< in: value to set */ - ulint offs, /*!< in: offset from the origin down */ - ulint mask, /*!< in: mask used to filter bits */ - ulint shift) /*!< in: shift right applied after masking */ -{ - ut_ad(rec); - ut_ad(offs <= REC_N_OLD_EXTRA_BYTES); - ut_ad(mask > 0xFFUL); - ut_ad(mask <= 0xFFFFUL); - ut_ad((mask >> shift) & 1); - ut_ad(0 == ((mask >> shift) & ((mask >> shift) + 1))); - ut_ad(((mask >> shift) << shift) == mask); - ut_ad(((val << shift) & mask) == (val << shift)); - - mach_write_to_2(rec - offs, - (mach_read_from_2(rec - offs) & ~mask) - | (val << shift)); -} - -/******************************************************//** -The following function is used to get the pointer of the next chained record -on the same page. -@return pointer to the next chained record, or NULL if none */ -UNIV_INLINE -const rec_t* -rec_get_next_ptr_const( -/*===================*/ - const rec_t* rec, /*!< in: physical record */ - ulint comp) /*!< in: nonzero=compact page format */ -{ - ulint field_value; - - ut_ad(REC_NEXT_MASK == 0xFFFFUL); - ut_ad(REC_NEXT_SHIFT == 0); - - field_value = mach_read_from_2(rec - REC_NEXT); - - if (field_value == 0) { - - return(NULL); - } - - if (comp) { -#if UNIV_PAGE_SIZE_MAX <= 32768 - /* Note that for 64 KiB pages, field_value can 'wrap around' - and the debug assertion is not valid */ - - /* In the following assertion, field_value is interpreted - as signed 16-bit integer in 2's complement arithmetics. - If all platforms defined int16_t in the standard headers, - the expression could be written simpler as - (int16_t) field_value + ut_align_offset(...) < UNIV_PAGE_SIZE - */ - ut_ad((field_value >= 32768 - ? field_value - 65536 - : field_value) - + ut_align_offset(rec, UNIV_PAGE_SIZE) - < UNIV_PAGE_SIZE); -#endif - /* There must be at least REC_N_NEW_EXTRA_BYTES + 1 - between each record. */ - ut_ad((field_value > REC_N_NEW_EXTRA_BYTES - && field_value < 32768) - || field_value < (uint16) -REC_N_NEW_EXTRA_BYTES); - - return((byte*) ut_align_down(rec, UNIV_PAGE_SIZE) - + ut_align_offset(rec + field_value, UNIV_PAGE_SIZE)); - } else { - ut_ad(field_value < UNIV_PAGE_SIZE); - - return((byte*) ut_align_down(rec, UNIV_PAGE_SIZE) - + field_value); - } -} - -/******************************************************//** -The following function is used to get the pointer of the next chained record -on the same page. -@return pointer to the next chained record, or NULL if none */ -UNIV_INLINE -rec_t* -rec_get_next_ptr( -/*=============*/ - rec_t* rec, /*!< in: physical record */ - ulint comp) /*!< in: nonzero=compact page format */ -{ - return(const_cast<rec_t*>(rec_get_next_ptr_const(rec, comp))); -} - -/******************************************************//** -The following function is used to get the offset of the next chained record -on the same page. -@return the page offset of the next chained record, or 0 if none */ -UNIV_INLINE -ulint -rec_get_next_offs( -/*==============*/ - const rec_t* rec, /*!< in: physical record */ - ulint comp) /*!< in: nonzero=compact page format */ -{ - ulint field_value; -#if REC_NEXT_MASK != 0xFFFFUL -# error "REC_NEXT_MASK != 0xFFFFUL" -#endif -#if REC_NEXT_SHIFT -# error "REC_NEXT_SHIFT != 0" -#endif - - field_value = mach_read_from_2(rec - REC_NEXT); - - if (comp) { -#if UNIV_PAGE_SIZE_MAX <= 32768 - /* Note that for 64 KiB pages, field_value can 'wrap around' - and the debug assertion is not valid */ - - /* In the following assertion, field_value is interpreted - as signed 16-bit integer in 2's complement arithmetics. - If all platforms defined int16_t in the standard headers, - the expression could be written simpler as - (int16_t) field_value + ut_align_offset(...) < UNIV_PAGE_SIZE - */ - ut_ad((field_value >= 32768 - ? field_value - 65536 - : field_value) - + ut_align_offset(rec, UNIV_PAGE_SIZE) - < UNIV_PAGE_SIZE); -#endif - if (field_value == 0) { - - return(0); - } - - /* There must be at least REC_N_NEW_EXTRA_BYTES + 1 - between each record. */ - ut_ad((field_value > REC_N_NEW_EXTRA_BYTES - && field_value < 32768) - || field_value < (uint16) -REC_N_NEW_EXTRA_BYTES); - - return(ut_align_offset(rec + field_value, UNIV_PAGE_SIZE)); - } else { - ut_ad(field_value < UNIV_PAGE_SIZE); - - return(field_value); - } -} - -/******************************************************//** -The following function is used to set the next record offset field -of an old-style record. */ -UNIV_INLINE -void -rec_set_next_offs_old( -/*==================*/ - rec_t* rec, /*!< in: old-style physical record */ - ulint next) /*!< in: offset of the next record */ -{ - ut_ad(rec); - ut_ad(UNIV_PAGE_SIZE > next); -#if REC_NEXT_MASK != 0xFFFFUL -# error "REC_NEXT_MASK != 0xFFFFUL" -#endif -#if REC_NEXT_SHIFT -# error "REC_NEXT_SHIFT != 0" -#endif - - mach_write_to_2(rec - REC_NEXT, next); -} - -/******************************************************//** -The following function is used to set the next record offset field -of a new-style record. */ -UNIV_INLINE -void -rec_set_next_offs_new( -/*==================*/ - rec_t* rec, /*!< in/out: new-style physical record */ - ulint next) /*!< in: offset of the next record */ -{ - ulint field_value; - - ut_ad(rec); - ut_ad(UNIV_PAGE_SIZE > next); - - if (!next) { - field_value = 0; - } else { - /* The following two statements calculate - next - offset_of_rec mod 64Ki, where mod is the modulo - as a non-negative number */ - - field_value = (ulint) - ((lint) next - - (lint) ut_align_offset(rec, UNIV_PAGE_SIZE)); - field_value &= REC_NEXT_MASK; - } - - mach_write_to_2(rec - REC_NEXT, field_value); -} - -/******************************************************//** -The following function is used to get the number of fields -in an old-style record. -@return number of data fields */ -UNIV_INLINE -ulint -rec_get_n_fields_old( -/*=================*/ - const rec_t* rec) /*!< in: physical record */ -{ - ulint ret; - - ut_ad(rec); - - ret = rec_get_bit_field_2(rec, REC_OLD_N_FIELDS, - REC_OLD_N_FIELDS_MASK, - REC_OLD_N_FIELDS_SHIFT); - ut_ad(ret <= REC_MAX_N_FIELDS); - ut_ad(ret > 0); - - return(ret); -} - -/******************************************************//** -The following function is used to set the number of fields -in an old-style record. */ -UNIV_INLINE -void -rec_set_n_fields_old( -/*=================*/ - rec_t* rec, /*!< in: physical record */ - ulint n_fields) /*!< in: the number of fields */ -{ - ut_ad(rec); - ut_ad(n_fields <= REC_MAX_N_FIELDS); - ut_ad(n_fields > 0); - - rec_set_bit_field_2(rec, n_fields, REC_OLD_N_FIELDS, - REC_OLD_N_FIELDS_MASK, REC_OLD_N_FIELDS_SHIFT); -} - -/******************************************************//** -The following function retrieves the status bits of a new-style record. -@return status bits */ -UNIV_INLINE -ulint -rec_get_status( -/*===========*/ - const rec_t* rec) /*!< in: physical record */ -{ - ulint ret; - - ut_ad(rec); - - ret = rec_get_bit_field_1(rec, REC_NEW_STATUS, - REC_NEW_STATUS_MASK, REC_NEW_STATUS_SHIFT); - ut_ad((ret & ~REC_NEW_STATUS_MASK) == 0); - - return(ret); -} - -/******************************************************//** -The following function is used to get the number of fields -in a record. -@return number of data fields */ -UNIV_INLINE -ulint -rec_get_n_fields( -/*=============*/ - const rec_t* rec, /*!< in: physical record */ - const dict_index_t* index) /*!< in: record descriptor */ -{ - ut_ad(rec); - ut_ad(index); - - if (!dict_table_is_comp(index->table)) { - return(rec_get_n_fields_old(rec)); - } - - switch (rec_get_status(rec)) { - case REC_STATUS_ORDINARY: - return(dict_index_get_n_fields(index)); - case REC_STATUS_NODE_PTR: - return(dict_index_get_n_unique_in_tree(index) + 1); - case REC_STATUS_INFIMUM: - case REC_STATUS_SUPREMUM: - return(1); - default: - ut_error; - return(ULINT_UNDEFINED); - } -} - -/******************************************************//** -The following function is used to get the number of records owned by the -previous directory record. -@return number of owned records */ -UNIV_INLINE -ulint -rec_get_n_owned_old( -/*================*/ - const rec_t* rec) /*!< in: old-style physical record */ -{ - return(rec_get_bit_field_1(rec, REC_OLD_N_OWNED, - REC_N_OWNED_MASK, REC_N_OWNED_SHIFT)); -} - -/******************************************************//** -The following function is used to set the number of owned records. */ -UNIV_INLINE -void -rec_set_n_owned_old( -/*================*/ - rec_t* rec, /*!< in: old-style physical record */ - ulint n_owned) /*!< in: the number of owned */ -{ - rec_set_bit_field_1(rec, n_owned, REC_OLD_N_OWNED, - REC_N_OWNED_MASK, REC_N_OWNED_SHIFT); -} - -/******************************************************//** -The following function is used to get the number of records owned by the -previous directory record. -@return number of owned records */ -UNIV_INLINE -ulint -rec_get_n_owned_new( -/*================*/ - const rec_t* rec) /*!< in: new-style physical record */ -{ - return(rec_get_bit_field_1(rec, REC_NEW_N_OWNED, - REC_N_OWNED_MASK, REC_N_OWNED_SHIFT)); -} - -/******************************************************//** -The following function is used to set the number of owned records. */ -UNIV_INLINE -void -rec_set_n_owned_new( -/*================*/ - rec_t* rec, /*!< in/out: new-style physical record */ - page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */ - ulint n_owned)/*!< in: the number of owned */ -{ - rec_set_bit_field_1(rec, n_owned, REC_NEW_N_OWNED, - REC_N_OWNED_MASK, REC_N_OWNED_SHIFT); - if (page_zip && rec_get_status(rec) != REC_STATUS_SUPREMUM) { - page_zip_rec_set_owned(page_zip, rec, n_owned); - } -} - -/******************************************************//** -The following function is used to retrieve the info bits of a record. -@return info bits */ -UNIV_INLINE -ulint -rec_get_info_bits( -/*==============*/ - const rec_t* rec, /*!< in: physical record */ - ulint comp) /*!< in: nonzero=compact page format */ -{ - return(rec_get_bit_field_1( - rec, comp ? REC_NEW_INFO_BITS : REC_OLD_INFO_BITS, - REC_INFO_BITS_MASK, REC_INFO_BITS_SHIFT)); -} - -/******************************************************//** -The following function is used to set the info bits of a record. */ -UNIV_INLINE -void -rec_set_info_bits_old( -/*==================*/ - rec_t* rec, /*!< in: old-style physical record */ - ulint bits) /*!< in: info bits */ -{ - rec_set_bit_field_1(rec, bits, REC_OLD_INFO_BITS, - REC_INFO_BITS_MASK, REC_INFO_BITS_SHIFT); -} -/******************************************************//** -The following function is used to set the info bits of a record. */ -UNIV_INLINE -void -rec_set_info_bits_new( -/*==================*/ - rec_t* rec, /*!< in/out: new-style physical record */ - ulint bits) /*!< in: info bits */ -{ - rec_set_bit_field_1(rec, bits, REC_NEW_INFO_BITS, - REC_INFO_BITS_MASK, REC_INFO_BITS_SHIFT); -} - -/******************************************************//** -The following function is used to set the status bits of a new-style record. */ -UNIV_INLINE -void -rec_set_status( -/*===========*/ - rec_t* rec, /*!< in/out: physical record */ - ulint bits) /*!< in: info bits */ -{ - rec_set_bit_field_1(rec, bits, REC_NEW_STATUS, - REC_NEW_STATUS_MASK, REC_NEW_STATUS_SHIFT); -} - -/******************************************************//** -The following function is used to retrieve the info and status -bits of a record. (Only compact records have status bits.) -@return info bits */ -UNIV_INLINE -ulint -rec_get_info_and_status_bits( -/*=========================*/ - const rec_t* rec, /*!< in: physical record */ - ulint comp) /*!< in: nonzero=compact page format */ -{ - ulint bits; -#if (REC_NEW_STATUS_MASK >> REC_NEW_STATUS_SHIFT) \ -& (REC_INFO_BITS_MASK >> REC_INFO_BITS_SHIFT) -# error "REC_NEW_STATUS_MASK and REC_INFO_BITS_MASK overlap" -#endif - if (comp) { - bits = rec_get_info_bits(rec, TRUE) | rec_get_status(rec); - } else { - bits = rec_get_info_bits(rec, FALSE); - ut_ad(!(bits & ~(REC_INFO_BITS_MASK >> REC_INFO_BITS_SHIFT))); - } - return(bits); -} -/******************************************************//** -The following function is used to set the info and status -bits of a record. (Only compact records have status bits.) */ -UNIV_INLINE -void -rec_set_info_and_status_bits( -/*=========================*/ - rec_t* rec, /*!< in/out: physical record */ - ulint bits) /*!< in: info bits */ -{ -#if (REC_NEW_STATUS_MASK >> REC_NEW_STATUS_SHIFT) \ -& (REC_INFO_BITS_MASK >> REC_INFO_BITS_SHIFT) -# error "REC_NEW_STATUS_MASK and REC_INFO_BITS_MASK overlap" -#endif - rec_set_status(rec, bits & REC_NEW_STATUS_MASK); - rec_set_info_bits_new(rec, bits & ~REC_NEW_STATUS_MASK); -} - -/******************************************************//** -The following function tells if record is delete marked. -@return nonzero if delete marked */ -UNIV_INLINE -ulint -rec_get_deleted_flag( -/*=================*/ - const rec_t* rec, /*!< in: physical record */ - ulint comp) /*!< in: nonzero=compact page format */ -{ - if (comp) { - return(rec_get_bit_field_1(rec, REC_NEW_INFO_BITS, - REC_INFO_DELETED_FLAG, - REC_INFO_BITS_SHIFT)); - } else { - return(rec_get_bit_field_1(rec, REC_OLD_INFO_BITS, - REC_INFO_DELETED_FLAG, - REC_INFO_BITS_SHIFT)); - } -} - -/******************************************************//** -The following function is used to set the deleted bit. */ -UNIV_INLINE -void -rec_set_deleted_flag_old( -/*=====================*/ - rec_t* rec, /*!< in: old-style physical record */ - ulint flag) /*!< in: nonzero if delete marked */ -{ - ulint val; - - val = rec_get_info_bits(rec, FALSE); - - if (flag) { - val |= REC_INFO_DELETED_FLAG; - } else { - val &= ~REC_INFO_DELETED_FLAG; - } - - rec_set_info_bits_old(rec, val); -} - -/******************************************************//** -The following function is used to set the deleted bit. */ -UNIV_INLINE -void -rec_set_deleted_flag_new( -/*=====================*/ - rec_t* rec, /*!< in/out: new-style physical record */ - page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */ - ulint flag) /*!< in: nonzero if delete marked */ -{ - ulint val; - - val = rec_get_info_bits(rec, TRUE); - - if (flag) { - val |= REC_INFO_DELETED_FLAG; - } else { - val &= ~REC_INFO_DELETED_FLAG; - } - - rec_set_info_bits_new(rec, val); - - if (page_zip) { - page_zip_rec_set_deleted(page_zip, rec, flag); - } -} - -/******************************************************//** -The following function tells if a new-style record is a node pointer. -@return TRUE if node pointer */ -UNIV_INLINE -ibool -rec_get_node_ptr_flag( -/*==================*/ - const rec_t* rec) /*!< in: physical record */ -{ - return(REC_STATUS_NODE_PTR == rec_get_status(rec)); -} - -/******************************************************//** -The following function is used to get the order number -of an old-style record in the heap of the index page. -@return heap order number */ -UNIV_INLINE -ulint -rec_get_heap_no_old( -/*================*/ - const rec_t* rec) /*!< in: physical record */ -{ - return(rec_get_bit_field_2(rec, REC_OLD_HEAP_NO, - REC_HEAP_NO_MASK, REC_HEAP_NO_SHIFT)); -} - -/******************************************************//** -The following function is used to set the heap number -field in an old-style record. */ -UNIV_INLINE -void -rec_set_heap_no_old( -/*================*/ - rec_t* rec, /*!< in: physical record */ - ulint heap_no)/*!< in: the heap number */ -{ - rec_set_bit_field_2(rec, heap_no, REC_OLD_HEAP_NO, - REC_HEAP_NO_MASK, REC_HEAP_NO_SHIFT); -} - -/******************************************************//** -The following function is used to get the order number -of a new-style record in the heap of the index page. -@return heap order number */ -UNIV_INLINE -ulint -rec_get_heap_no_new( -/*================*/ - const rec_t* rec) /*!< in: physical record */ -{ - return(rec_get_bit_field_2(rec, REC_NEW_HEAP_NO, - REC_HEAP_NO_MASK, REC_HEAP_NO_SHIFT)); -} - -/******************************************************//** -The following function is used to set the heap number -field in a new-style record. */ -UNIV_INLINE -void -rec_set_heap_no_new( -/*================*/ - rec_t* rec, /*!< in/out: physical record */ - ulint heap_no)/*!< in: the heap number */ -{ - rec_set_bit_field_2(rec, heap_no, REC_NEW_HEAP_NO, - REC_HEAP_NO_MASK, REC_HEAP_NO_SHIFT); -} - -/******************************************************//** -The following function is used to test whether the data offsets in the record -are stored in one-byte or two-byte format. -@return TRUE if 1-byte form */ -UNIV_INLINE -ibool -rec_get_1byte_offs_flag( -/*====================*/ - const rec_t* rec) /*!< in: physical record */ -{ -#if TRUE != 1 -#error "TRUE != 1" -#endif - - return(rec_get_bit_field_1(rec, REC_OLD_SHORT, REC_OLD_SHORT_MASK, - REC_OLD_SHORT_SHIFT)); -} - -/******************************************************//** -The following function is used to set the 1-byte offsets flag. */ -UNIV_INLINE -void -rec_set_1byte_offs_flag( -/*====================*/ - rec_t* rec, /*!< in: physical record */ - ibool flag) /*!< in: TRUE if 1byte form */ -{ -#if TRUE != 1 -#error "TRUE != 1" -#endif - ut_ad(flag <= TRUE); - - rec_set_bit_field_1(rec, flag, REC_OLD_SHORT, REC_OLD_SHORT_MASK, - REC_OLD_SHORT_SHIFT); -} - -/******************************************************//** -Returns the offset of nth field end if the record is stored in the 1-byte -offsets form. If the field is SQL null, the flag is ORed in the returned -value. -@return offset of the start of the field, SQL null flag ORed */ -UNIV_INLINE -ulint -rec_1_get_field_end_info( -/*=====================*/ - const rec_t* rec, /*!< in: record */ - ulint n) /*!< in: field index */ -{ - ut_ad(rec_get_1byte_offs_flag(rec)); - ut_ad(n < rec_get_n_fields_old(rec)); - - return(mach_read_from_1(rec - (REC_N_OLD_EXTRA_BYTES + n + 1))); -} - -/******************************************************//** -Returns the offset of nth field end if the record is stored in the 2-byte -offsets form. If the field is SQL null, the flag is ORed in the returned -value. -@return offset of the start of the field, SQL null flag and extern -storage flag ORed */ -UNIV_INLINE -ulint -rec_2_get_field_end_info( -/*=====================*/ - const rec_t* rec, /*!< in: record */ - ulint n) /*!< in: field index */ -{ - ut_ad(!rec_get_1byte_offs_flag(rec)); - ut_ad(n < rec_get_n_fields_old(rec)); - - return(mach_read_from_2(rec - (REC_N_OLD_EXTRA_BYTES + 2 * n + 2))); -} - -/******************************************************//** -Returns nonzero if the field is stored off-page. -@retval 0 if the field is stored in-page -@retval REC_2BYTE_EXTERN_MASK if the field is stored externally */ -UNIV_INLINE -ulint -rec_2_is_field_extern( -/*==================*/ - const rec_t* rec, /*!< in: record */ - ulint n) /*!< in: field index */ -{ - return(rec_2_get_field_end_info(rec, n) & REC_2BYTE_EXTERN_MASK); -} - -/* Get the base address of offsets. The extra_size is stored at -this position, and following positions hold the end offsets of -the fields. */ -#define rec_offs_base(offsets) (offsets + REC_OFFS_HEADER_SIZE) - -/**********************************************************//** -The following function returns the number of allocated elements -for an array of offsets. -@return number of elements */ -UNIV_INLINE -ulint -rec_offs_get_n_alloc( -/*=================*/ - const ulint* offsets)/*!< in: array for rec_get_offsets() */ -{ - ulint n_alloc; - ut_ad(offsets); - n_alloc = offsets[0]; - ut_ad(n_alloc > REC_OFFS_HEADER_SIZE); - UNIV_MEM_ASSERT_W(offsets, n_alloc * sizeof *offsets); - return(n_alloc); -} - -/**********************************************************//** -The following function sets the number of allocated elements -for an array of offsets. */ -UNIV_INLINE -void -rec_offs_set_n_alloc( -/*=================*/ - ulint* offsets, /*!< out: array for rec_get_offsets(), - must be allocated */ - ulint n_alloc) /*!< in: number of elements */ -{ - ut_ad(offsets); - ut_ad(n_alloc > REC_OFFS_HEADER_SIZE); - UNIV_MEM_ASSERT_AND_ALLOC(offsets, n_alloc * sizeof *offsets); - offsets[0] = n_alloc; -} - -/**********************************************************//** -The following function returns the number of fields in a record. -@return number of fields */ -UNIV_INLINE -ulint -rec_offs_n_fields( -/*==============*/ - const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ -{ - ulint n_fields; - ut_ad(offsets); - n_fields = offsets[1]; - ut_ad(n_fields > 0); - ut_ad(n_fields <= REC_MAX_N_FIELDS); - ut_ad(n_fields + REC_OFFS_HEADER_SIZE - <= rec_offs_get_n_alloc(offsets)); - return(n_fields); -} - -/************************************************************//** -Validates offsets returned by rec_get_offsets(). -@return TRUE if valid */ -UNIV_INLINE -ibool -rec_offs_validate( -/*==============*/ - const rec_t* rec, /*!< in: record or NULL */ - const dict_index_t* index, /*!< in: record descriptor or NULL */ - const ulint* offsets)/*!< in: array returned by - rec_get_offsets() */ -{ - ulint i = rec_offs_n_fields(offsets); - ulint last = ULINT_MAX; - ulint comp = *rec_offs_base(offsets) & REC_OFFS_COMPACT; - - if (rec) { - ut_ad((ulint) rec == offsets[2]); - if (!comp) { - ut_a(rec_get_n_fields_old(rec) >= i); - } - } - if (index) { - ulint max_n_fields; - ut_ad((ulint) index == offsets[3]); - max_n_fields = ut_max( - dict_index_get_n_fields(index), - dict_index_get_n_unique_in_tree(index) + 1); - if (comp && rec) { - switch (rec_get_status(rec)) { - case REC_STATUS_ORDINARY: - break; - case REC_STATUS_NODE_PTR: - max_n_fields = dict_index_get_n_unique_in_tree( - index) + 1; - break; - case REC_STATUS_INFIMUM: - case REC_STATUS_SUPREMUM: - max_n_fields = 1; - break; - default: - ut_error; - } - } - /* index->n_def == 0 for dummy indexes if !comp */ - ut_a(!comp || index->n_def); - ut_a(!index->n_def || i <= max_n_fields); - } - while (i--) { - ulint curr = rec_offs_base(offsets)[1 + i] & REC_OFFS_MASK; - ut_a(curr <= last); - last = curr; - } - return(TRUE); -} -#ifdef UNIV_DEBUG -/************************************************************//** -Updates debug data in offsets, in order to avoid bogus -rec_offs_validate() failures. */ -UNIV_INLINE -void -rec_offs_make_valid( -/*================*/ - const rec_t* rec, /*!< in: record */ - const dict_index_t* index, /*!< in: record descriptor */ - ulint* offsets)/*!< in: array returned by - rec_get_offsets() */ -{ - ut_ad(rec); - ut_ad(index); - ut_ad(offsets); - ut_ad(rec_get_n_fields(rec, index) >= rec_offs_n_fields(offsets)); - offsets[2] = (ulint) rec; - offsets[3] = (ulint) index; -} -#endif /* UNIV_DEBUG */ - -/************************************************************//** -The following function is used to get an offset to the nth -data field in a record. -@return offset from the origin of rec */ -UNIV_INLINE -ulint -rec_get_nth_field_offs( -/*===================*/ - const ulint* offsets,/*!< in: array returned by rec_get_offsets() */ - ulint n, /*!< in: index of the field */ - ulint* len) /*!< out: length of the field; UNIV_SQL_NULL - if SQL null */ -{ - ulint offs; - ulint length; - ut_ad(n < rec_offs_n_fields(offsets)); - ut_ad(len); - - if (n == 0) { - offs = 0; - } else { - offs = rec_offs_base(offsets)[n] & REC_OFFS_MASK; - } - - length = rec_offs_base(offsets)[1 + n]; - - if (length & REC_OFFS_SQL_NULL) { - length = UNIV_SQL_NULL; - } else { - length &= REC_OFFS_MASK; - length -= offs; - } - - *len = length; - return(offs); -} - -/******************************************************//** -Determine if the offsets are for a record in the new -compact format. -@return nonzero if compact format */ -UNIV_INLINE -ulint -rec_offs_comp( -/*==========*/ - const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ -{ - ut_ad(rec_offs_validate(NULL, NULL, offsets)); - return(*rec_offs_base(offsets) & REC_OFFS_COMPACT); -} - -/******************************************************//** -Determine if the offsets are for a record containing -externally stored columns. -@return nonzero if externally stored */ -UNIV_INLINE -ulint -rec_offs_any_extern( -/*================*/ - const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ -{ - ut_ad(rec_offs_validate(NULL, NULL, offsets)); - return(*rec_offs_base(offsets) & REC_OFFS_EXTERNAL); -} - -/******************************************************//** -Determine if the offsets are for a record containing null BLOB pointers. -@return first field containing a null BLOB pointer, or NULL if none found */ -UNIV_INLINE -const byte* -rec_offs_any_null_extern( -/*=====================*/ - const rec_t* rec, /*!< in: record */ - const ulint* offsets) /*!< in: rec_get_offsets(rec) */ -{ - ulint i; - ut_ad(rec_offs_validate(rec, NULL, offsets)); - - if (!rec_offs_any_extern(offsets)) { - return(NULL); - } - - for (i = 0; i < rec_offs_n_fields(offsets); i++) { - if (rec_offs_nth_extern(offsets, i)) { - ulint len; - const byte* field - = rec_get_nth_field(rec, offsets, i, &len); - - ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE); - if (!memcmp(field + len - - BTR_EXTERN_FIELD_REF_SIZE, - field_ref_zero, - BTR_EXTERN_FIELD_REF_SIZE)) { - return(field); - } - } - } - - return(NULL); -} - -/******************************************************//** -Returns nonzero if the extern bit is set in nth field of rec. -@return nonzero if externally stored */ -UNIV_INLINE -ulint -rec_offs_nth_extern( -/*================*/ - const ulint* offsets,/*!< in: array returned by rec_get_offsets() */ - ulint n) /*!< in: nth field */ -{ - ut_ad(rec_offs_validate(NULL, NULL, offsets)); - ut_ad(n < rec_offs_n_fields(offsets)); - return(rec_offs_base(offsets)[1 + n] & REC_OFFS_EXTERNAL); -} - -/******************************************************//** -Returns nonzero if the SQL NULL bit is set in nth field of rec. -@return nonzero if SQL NULL */ -UNIV_INLINE -ulint -rec_offs_nth_sql_null( -/*==================*/ - const ulint* offsets,/*!< in: array returned by rec_get_offsets() */ - ulint n) /*!< in: nth field */ -{ - ut_ad(rec_offs_validate(NULL, NULL, offsets)); - ut_ad(n < rec_offs_n_fields(offsets)); - return(rec_offs_base(offsets)[1 + n] & REC_OFFS_SQL_NULL); -} - -/******************************************************//** -Gets the physical size of a field. -@return length of field */ -UNIV_INLINE -ulint -rec_offs_nth_size( -/*==============*/ - const ulint* offsets,/*!< in: array returned by rec_get_offsets() */ - ulint n) /*!< in: nth field */ -{ - ut_ad(rec_offs_validate(NULL, NULL, offsets)); - ut_ad(n < rec_offs_n_fields(offsets)); - if (!n) { - return(rec_offs_base(offsets)[1 + n] & REC_OFFS_MASK); - } - return((rec_offs_base(offsets)[1 + n] - rec_offs_base(offsets)[n]) - & REC_OFFS_MASK); -} - -/******************************************************//** -Returns the number of extern bits set in a record. -@return number of externally stored fields */ -UNIV_INLINE -ulint -rec_offs_n_extern( -/*==============*/ - const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ -{ - ulint n = 0; - - if (rec_offs_any_extern(offsets)) { - ulint i; - - for (i = rec_offs_n_fields(offsets); i--; ) { - if (rec_offs_nth_extern(offsets, i)) { - n++; - } - } - } - - return(n); -} - -/******************************************************//** -Returns the offset of n - 1th field end if the record is stored in the 1-byte -offsets form. If the field is SQL null, the flag is ORed in the returned -value. This function and the 2-byte counterpart are defined here because the -C-compiler was not able to sum negative and positive constant offsets, and -warned of constant arithmetic overflow within the compiler. -@return offset of the start of the PREVIOUS field, SQL null flag ORed */ -UNIV_INLINE -ulint -rec_1_get_prev_field_end_info( -/*==========================*/ - const rec_t* rec, /*!< in: record */ - ulint n) /*!< in: field index */ -{ - ut_ad(rec_get_1byte_offs_flag(rec)); - ut_ad(n <= rec_get_n_fields_old(rec)); - - return(mach_read_from_1(rec - (REC_N_OLD_EXTRA_BYTES + n))); -} - -/******************************************************//** -Returns the offset of n - 1th field end if the record is stored in the 2-byte -offsets form. If the field is SQL null, the flag is ORed in the returned -value. -@return offset of the start of the PREVIOUS field, SQL null flag ORed */ -UNIV_INLINE -ulint -rec_2_get_prev_field_end_info( -/*==========================*/ - const rec_t* rec, /*!< in: record */ - ulint n) /*!< in: field index */ -{ - ut_ad(!rec_get_1byte_offs_flag(rec)); - ut_ad(n <= rec_get_n_fields_old(rec)); - - return(mach_read_from_2(rec - (REC_N_OLD_EXTRA_BYTES + 2 * n))); -} - -/******************************************************//** -Sets the field end info for the nth field if the record is stored in the -1-byte format. */ -UNIV_INLINE -void -rec_1_set_field_end_info( -/*=====================*/ - rec_t* rec, /*!< in: record */ - ulint n, /*!< in: field index */ - ulint info) /*!< in: value to set */ -{ - ut_ad(rec_get_1byte_offs_flag(rec)); - ut_ad(n < rec_get_n_fields_old(rec)); - - mach_write_to_1(rec - (REC_N_OLD_EXTRA_BYTES + n + 1), info); -} - -/******************************************************//** -Sets the field end info for the nth field if the record is stored in the -2-byte format. */ -UNIV_INLINE -void -rec_2_set_field_end_info( -/*=====================*/ - rec_t* rec, /*!< in: record */ - ulint n, /*!< in: field index */ - ulint info) /*!< in: value to set */ -{ - ut_ad(!rec_get_1byte_offs_flag(rec)); - ut_ad(n < rec_get_n_fields_old(rec)); - - mach_write_to_2(rec - (REC_N_OLD_EXTRA_BYTES + 2 * n + 2), info); -} - -/******************************************************//** -Returns the offset of nth field start if the record is stored in the 1-byte -offsets form. -@return offset of the start of the field */ -UNIV_INLINE -ulint -rec_1_get_field_start_offs( -/*=======================*/ - const rec_t* rec, /*!< in: record */ - ulint n) /*!< in: field index */ -{ - ut_ad(rec_get_1byte_offs_flag(rec)); - ut_ad(n <= rec_get_n_fields_old(rec)); - - if (n == 0) { - - return(0); - } - - return(rec_1_get_prev_field_end_info(rec, n) - & ~REC_1BYTE_SQL_NULL_MASK); -} - -/******************************************************//** -Returns the offset of nth field start if the record is stored in the 2-byte -offsets form. -@return offset of the start of the field */ -UNIV_INLINE -ulint -rec_2_get_field_start_offs( -/*=======================*/ - const rec_t* rec, /*!< in: record */ - ulint n) /*!< in: field index */ -{ - ut_ad(!rec_get_1byte_offs_flag(rec)); - ut_ad(n <= rec_get_n_fields_old(rec)); - - if (n == 0) { - - return(0); - } - - return(rec_2_get_prev_field_end_info(rec, n) - & ~(REC_2BYTE_SQL_NULL_MASK | REC_2BYTE_EXTERN_MASK)); -} - -/******************************************************//** -The following function is used to read the offset of the start of a data field -in the record. The start of an SQL null field is the end offset of the -previous non-null field, or 0, if none exists. If n is the number of the last -field + 1, then the end offset of the last field is returned. -@return offset of the start of the field */ -UNIV_INLINE -ulint -rec_get_field_start_offs( -/*=====================*/ - const rec_t* rec, /*!< in: record */ - ulint n) /*!< in: field index */ -{ - ut_ad(rec); - ut_ad(n <= rec_get_n_fields_old(rec)); - - if (n == 0) { - - return(0); - } - - if (rec_get_1byte_offs_flag(rec)) { - - return(rec_1_get_field_start_offs(rec, n)); - } - - return(rec_2_get_field_start_offs(rec, n)); -} - -/************************************************************//** -Gets the physical size of an old-style field. -Also an SQL null may have a field of size > 0, -if the data type is of a fixed size. -@return field size in bytes */ -UNIV_INLINE -ulint -rec_get_nth_field_size( -/*===================*/ - const rec_t* rec, /*!< in: record */ - ulint n) /*!< in: index of the field */ -{ - ulint os; - ulint next_os; - - os = rec_get_field_start_offs(rec, n); - next_os = rec_get_field_start_offs(rec, n + 1); - - ut_ad(next_os - os < UNIV_PAGE_SIZE); - - return(next_os - os); -} - -/***********************************************************//** -This is used to modify the value of an already existing field in a record. -The previous value must have exactly the same size as the new value. If len -is UNIV_SQL_NULL then the field is treated as an SQL null. -For records in ROW_FORMAT=COMPACT (new-style records), len must not be -UNIV_SQL_NULL unless the field already is SQL null. */ -UNIV_INLINE -void -rec_set_nth_field( -/*==============*/ - rec_t* rec, /*!< in: record */ - const ulint* offsets,/*!< in: array returned by rec_get_offsets() */ - ulint n, /*!< in: index number of the field */ - const void* data, /*!< in: pointer to the data - if not SQL null */ - ulint len) /*!< in: length of the data or UNIV_SQL_NULL */ -{ - byte* data2; - ulint len2; - - ut_ad(rec); - ut_ad(rec_offs_validate(rec, NULL, offsets)); - - if (len == UNIV_SQL_NULL) { - if (!rec_offs_nth_sql_null(offsets, n)) { - ut_a(!rec_offs_comp(offsets)); - rec_set_nth_field_sql_null(rec, n); - } - - return; - } - - data2 = rec_get_nth_field(rec, offsets, n, &len2); - if (len2 == UNIV_SQL_NULL) { - ut_ad(!rec_offs_comp(offsets)); - rec_set_nth_field_null_bit(rec, n, FALSE); - ut_ad(len == rec_get_nth_field_size(rec, n)); - } else { - ut_ad(len2 == len); - } - - ut_memcpy(data2, data, len); -} - -/**********************************************************//** -The following function returns the data size of an old-style physical -record, that is the sum of field lengths. SQL null fields -are counted as length 0 fields. The value returned by the function -is the distance from record origin to record end in bytes. -@return size */ -UNIV_INLINE -ulint -rec_get_data_size_old( -/*==================*/ - const rec_t* rec) /*!< in: physical record */ -{ - ut_ad(rec); - - return(rec_get_field_start_offs(rec, rec_get_n_fields_old(rec))); -} - -/**********************************************************//** -The following function sets the number of fields in offsets. */ -UNIV_INLINE -void -rec_offs_set_n_fields( -/*==================*/ - ulint* offsets, /*!< in/out: array returned by - rec_get_offsets() */ - ulint n_fields) /*!< in: number of fields */ -{ - ut_ad(offsets); - ut_ad(n_fields > 0); - ut_ad(n_fields <= REC_MAX_N_FIELDS); - ut_ad(n_fields + REC_OFFS_HEADER_SIZE - <= rec_offs_get_n_alloc(offsets)); - offsets[1] = n_fields; -} - -/**********************************************************//** -The following function returns the data size of a physical -record, that is the sum of field lengths. SQL null fields -are counted as length 0 fields. The value returned by the function -is the distance from record origin to record end in bytes. -@return size */ -UNIV_INLINE -ulint -rec_offs_data_size( -/*===============*/ - const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ -{ - ulint size; - - ut_ad(rec_offs_validate(NULL, NULL, offsets)); - size = rec_offs_base(offsets)[rec_offs_n_fields(offsets)] - & REC_OFFS_MASK; - ut_ad(size < UNIV_PAGE_SIZE); - return(size); -} - -/**********************************************************//** -Returns the total size of record minus data size of record. The value -returned by the function is the distance from record start to record origin -in bytes. -@return size */ -UNIV_INLINE -ulint -rec_offs_extra_size( -/*================*/ - const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ -{ - ulint size; - ut_ad(rec_offs_validate(NULL, NULL, offsets)); - size = *rec_offs_base(offsets) & ~(REC_OFFS_COMPACT | REC_OFFS_EXTERNAL); - ut_ad(size < UNIV_PAGE_SIZE); - return(size); -} - -/**********************************************************//** -Returns the total size of a physical record. -@return size */ -UNIV_INLINE -ulint -rec_offs_size( -/*==========*/ - const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ -{ - return(rec_offs_data_size(offsets) + rec_offs_extra_size(offsets)); -} - -#ifdef UNIV_DEBUG -/**********************************************************//** -Returns a pointer to the end of the record. -@return pointer to end */ -UNIV_INLINE -byte* -rec_get_end( -/*========*/ - const rec_t* rec, /*!< in: pointer to record */ - const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ -{ - ut_ad(rec_offs_validate(rec, NULL, offsets)); - return(const_cast<rec_t*>(rec + rec_offs_data_size(offsets))); -} - -/**********************************************************//** -Returns a pointer to the start of the record. -@return pointer to start */ -UNIV_INLINE -byte* -rec_get_start( -/*==========*/ - const rec_t* rec, /*!< in: pointer to record */ - const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ -{ - ut_ad(rec_offs_validate(rec, NULL, offsets)); - return(const_cast<rec_t*>(rec - rec_offs_extra_size(offsets))); -} -#endif /* UNIV_DEBUG */ - -/***************************************************************//** -Copies a physical record to a buffer. -@return pointer to the origin of the copy */ -UNIV_INLINE -rec_t* -rec_copy( -/*=====*/ - void* buf, /*!< in: buffer */ - const rec_t* rec, /*!< in: physical record */ - const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ -{ - ulint extra_len; - ulint data_len; - - ut_ad(rec != NULL); - ut_ad(buf != NULL); - ut_ad(rec_offs_validate(rec, NULL, offsets)); - ut_ad(rec_validate(rec, offsets)); - - extra_len = rec_offs_extra_size(offsets); - data_len = rec_offs_data_size(offsets); - - ut_memcpy(buf, rec - extra_len, extra_len + data_len); - - return((byte*) buf + extra_len); -} - -/**********************************************************//** -Returns the extra size of an old-style physical record if we know its -data size and number of fields. -@return extra size */ -UNIV_INLINE -ulint -rec_get_converted_extra_size( -/*=========================*/ - ulint data_size, /*!< in: data size */ - ulint n_fields, /*!< in: number of fields */ - ulint n_ext) /*!< in: number of externally stored columns */ -{ - if (!n_ext && data_size <= REC_1BYTE_OFFS_LIMIT) { - - return(REC_N_OLD_EXTRA_BYTES + n_fields); - } - - return(REC_N_OLD_EXTRA_BYTES + 2 * n_fields); -} - -/**********************************************************//** -The following function returns the size of a data tuple when converted to -a physical record. -@return size */ -UNIV_INLINE -ulint -rec_get_converted_size( -/*===================*/ - dict_index_t* index, /*!< in: record descriptor */ - const dtuple_t* dtuple, /*!< in: data tuple */ - ulint n_ext) /*!< in: number of externally stored columns */ -{ - ulint data_size; - ulint extra_size; - - ut_ad(index); - ut_ad(dtuple); - ut_ad(dtuple_check_typed(dtuple)); - - ut_ad(dict_index_is_univ(index) - || dtuple_get_n_fields(dtuple) - == (((dtuple_get_info_bits(dtuple) & REC_NEW_STATUS_MASK) - == REC_STATUS_NODE_PTR) - ? dict_index_get_n_unique_in_tree(index) + 1 - : dict_index_get_n_fields(index))); - - if (dict_table_is_comp(index->table)) { - return(rec_get_converted_size_comp(index, - dtuple_get_info_bits(dtuple) - & REC_NEW_STATUS_MASK, - dtuple->fields, - dtuple->n_fields, NULL)); - } - - data_size = dtuple_get_data_size(dtuple, 0); - - extra_size = rec_get_converted_extra_size( - data_size, dtuple_get_n_fields(dtuple), n_ext); - -#if 0 - /* This code is inactive since it may be the wrong place to add - in the size of node pointers used in parent pages AND it is not - currently needed since ha_innobase::max_supported_key_length() - ensures that the key size limit for each page size is well below - the actual limit ((free space on page / 4) - record overhead). - But those limits will need to be raised when InnoDB can - support multiple page sizes. At that time, we will need - to consider the node pointer on these universal btrees. */ - - if (dict_index_is_univ(index)) { - /* This is for the insert buffer B-tree. - All fields in the leaf tuple ascend to the - parent node plus the child page pointer. */ - - /* ibuf cannot contain externally stored fields */ - ut_ad(n_ext == 0); - - /* Add the data pointer and recompute extra_size - based on one more field. */ - data_size += REC_NODE_PTR_SIZE; - extra_size = rec_get_converted_extra_size( - data_size, - dtuple_get_n_fields(dtuple) + 1, - 0); - - /* Be sure dtuple->n_fields has this node ptr - accounted for. This function should correspond to - what rec_convert_dtuple_to_rec() needs in storage. - In optimistic insert or update-not-in-place, we will - have to ensure that if the record is converted to a - node pointer, it will not become too large.*/ - } -#endif - - return(data_size + extra_size); -} - -#ifndef UNIV_HOTBACKUP -/************************************************************//** -Folds a prefix of a physical record to a ulint. Folds only existing fields, -that is, checks that we do not run out of the record. -@return the folded value */ -UNIV_INLINE -ulint -rec_fold( -/*=====*/ - const rec_t* rec, /*!< in: the physical record */ - const ulint* offsets, /*!< in: array returned by - rec_get_offsets() */ - ulint n_fields, /*!< in: number of complete - fields to fold */ - ulint n_bytes, /*!< in: number of bytes to fold - in an incomplete last field */ - index_id_t tree_id) /*!< in: index tree id */ -{ - ulint i; - const byte* data; - ulint len; - ulint fold; - ulint n_fields_rec; - - ut_ad(rec_offs_validate(rec, NULL, offsets)); - ut_ad(rec_validate(rec, offsets)); - ut_ad(n_fields + n_bytes > 0); - - n_fields_rec = rec_offs_n_fields(offsets); - ut_ad(n_fields <= n_fields_rec); - ut_ad(n_fields < n_fields_rec || n_bytes == 0); - - if (n_fields > n_fields_rec) { - n_fields = n_fields_rec; - } - - if (n_fields == n_fields_rec) { - n_bytes = 0; - } - - fold = ut_fold_ull(tree_id); - - for (i = 0; i < n_fields; i++) { - data = rec_get_nth_field(rec, offsets, i, &len); - - if (len != UNIV_SQL_NULL) { - fold = ut_fold_ulint_pair(fold, - ut_fold_binary(data, len)); - } - } - - if (n_bytes > 0) { - data = rec_get_nth_field(rec, offsets, i, &len); - - if (len != UNIV_SQL_NULL) { - if (len > n_bytes) { - len = n_bytes; - } - - fold = ut_fold_ulint_pair(fold, - ut_fold_binary(data, len)); - } - } - - return(fold); -} -#endif /* !UNIV_HOTBACKUP */ |