diff options
Diffstat (limited to 'storage/innobase/include/row0row.h')
-rw-r--r-- | storage/innobase/include/row0row.h | 431 |
1 files changed, 431 insertions, 0 deletions
diff --git a/storage/innobase/include/row0row.h b/storage/innobase/include/row0row.h new file mode 100644 index 00000000..a1350740 --- /dev/null +++ b/storage/innobase/include/row0row.h @@ -0,0 +1,431 @@ +/***************************************************************************** + +Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2016, 2022, MariaDB Corporation. + +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, Fifth Floor, Boston, MA 02110-1335 USA + +*****************************************************************************/ + +/**************************************************//** +@file include/row0row.h +General row routines + +Created 4/20/1996 Heikki Tuuri +*******************************************************/ + +#ifndef row0row_h +#define row0row_h + +#include "que0types.h" +#include "ibuf0ibuf.h" +#include "trx0types.h" +#include "mtr0mtr.h" +#include "rem0types.h" +#include "row0types.h" +#include "btr0types.h" + +/*********************************************************************//** +Gets the offset of the DB_TRX_ID field, in bytes relative to the origin of +a clustered index record. +@return offset of DATA_TRX_ID */ +UNIV_INLINE +ulint +row_get_trx_id_offset( +/*==================*/ + const dict_index_t* index, /*!< in: clustered index */ + const rec_offs* offsets)/*!< in: record offsets */ + MY_ATTRIBUTE((nonnull, warn_unused_result)); +/*********************************************************************//** +Reads the trx id field from a clustered index record. +@return value of the field */ +UNIV_INLINE +trx_id_t +row_get_rec_trx_id( +/*===============*/ + const rec_t* rec, /*!< in: record */ + const dict_index_t* index, /*!< in: clustered index */ + const rec_offs* offsets)/*!< in: rec_get_offsets(rec, index) */ + MY_ATTRIBUTE((nonnull, warn_unused_result)); +/*********************************************************************//** +Reads the roll pointer field from a clustered index record. +@return value of the field */ +UNIV_INLINE +roll_ptr_t +row_get_rec_roll_ptr( +/*=================*/ + const rec_t* rec, /*!< in: record */ + const dict_index_t* index, /*!< in: clustered index */ + const rec_offs* offsets)/*!< in: rec_get_offsets(rec, index) */ + MY_ATTRIBUTE((nonnull, warn_unused_result)); + +/* Flags for row build type. */ +#define ROW_BUILD_NORMAL 0 /*!< build index row */ +#define ROW_BUILD_FOR_PURGE 1 /*!< build row for purge. */ +#define ROW_BUILD_FOR_UNDO 2 /*!< build row for undo. */ +#define ROW_BUILD_FOR_INSERT 3 /*!< build row for insert. */ + +/*****************************************************************//** +When an insert or purge to a table is performed, this function builds +the entry to be inserted into or purged from an index on the table. +@return index entry which should be inserted or purged +@retval NULL if the externally stored columns in the clustered index record +are unavailable and ext != NULL, or row is missing some needed columns. */ +dtuple_t* +row_build_index_entry_low( +/*======================*/ + const dtuple_t* row, /*!< in: row which should be + inserted or purged */ + const row_ext_t* ext, /*!< in: externally stored column + prefixes, or NULL */ + const dict_index_t* index, /*!< in: index on the table */ + mem_heap_t* heap, /*!< in,out: memory heap from which + the memory for the index entry + is allocated */ + ulint flag) /*!< in: ROW_BUILD_NORMAL, + ROW_BUILD_FOR_PURGE + or ROW_BUILD_FOR_UNDO */ + MY_ATTRIBUTE((warn_unused_result, nonnull(1,3,4))); +/*****************************************************************//** +When an insert or purge to a table is performed, this function builds +the entry to be inserted into or purged from an index on the table. +@return index entry which should be inserted or purged, or NULL if the +externally stored columns in the clustered index record are +unavailable and ext != NULL */ +UNIV_INLINE +dtuple_t* +row_build_index_entry( +/*==================*/ + const dtuple_t* row, /*!< in: row which should be + inserted or purged */ + const row_ext_t* ext, /*!< in: externally stored column + prefixes, or NULL */ + const dict_index_t* index, /*!< in: index on the table */ + mem_heap_t* heap) /*!< in,out: memory heap from which + the memory for the index entry + is allocated */ + MY_ATTRIBUTE((warn_unused_result, nonnull(1,3,4))); +/*******************************************************************//** +An inverse function to row_build_index_entry. Builds a row from a +record in a clustered index. +@return own: row built; see the NOTE below! */ +dtuple_t* +row_build( +/*======*/ + ulint type, /*!< in: ROW_COPY_POINTERS or + ROW_COPY_DATA; the latter + copies also the data fields to + heap while the first only + places pointers to data fields + on the index page, and thus is + more efficient */ + const dict_index_t* index, /*!< in: clustered index */ + const rec_t* rec, /*!< in: record in the clustered + index; NOTE: in the case + ROW_COPY_POINTERS the data + fields in the row will point + directly into this record, + therefore, the buffer page of + this record must be at least + s-latched and the latch held + as long as the row dtuple is used! */ + const rec_offs* offsets,/*!< in: rec_get_offsets(rec,index) + or NULL, in which case this function + will invoke rec_get_offsets() */ + const dict_table_t* col_table, + /*!< in: table, to check which + externally stored columns + occur in the ordering columns + of an index, or NULL if + index->table should be + consulted instead; the user + columns in this table should be + the same columns as in index->table */ + const dtuple_t* defaults, + /*!< in: default values of + added, changed columns, or NULL */ + const ulint* col_map,/*!< in: mapping of old column + numbers to new ones, or NULL */ + row_ext_t** ext, /*!< out, own: cache of + externally stored column + prefixes, or NULL */ + mem_heap_t* heap); /*!< in: memory heap from which + the memory needed is allocated */ + +/** An inverse function to row_build_index_entry. Builds a row from a +record in a clustered index, with possible indexing on ongoing +addition of new virtual columns. +@param[in] type ROW_COPY_POINTERS or ROW_COPY_DATA; +@param[in] index clustered index +@param[in] rec record in the clustered index +@param[in] offsets rec_get_offsets(rec,index) or NULL +@param[in] col_table table, to check which + externally stored columns + occur in the ordering columns + of an index, or NULL if + index->table should be + consulted instead +@param[in] defaults default values of added, changed columns, or NULL +@param[in] add_v new virtual columns added + along with new indexes +@param[in] col_map mapping of old column + numbers to new ones, or NULL +@param[in] ext cache of externally stored column + prefixes, or NULL +@param[in] heap memory heap from which + the memory needed is allocated +@return own: row built */ +dtuple_t* +row_build_w_add_vcol( + ulint type, + const dict_index_t* index, + const rec_t* rec, + const rec_offs* offsets, + const dict_table_t* col_table, + const dtuple_t* defaults, + const dict_add_v_col_t* add_v, + const ulint* col_map, + row_ext_t** ext, + mem_heap_t* heap); + +/*******************************************************************//** +Converts an index record to a typed data tuple. +@return index entry built; does not set info_bits, and the data fields +in the entry will point directly to rec */ +dtuple_t* +row_rec_to_index_entry_low( +/*=======================*/ + const rec_t* rec, /*!< in: record in the index */ + const dict_index_t* index, /*!< in: index */ + const rec_offs* offsets,/*!< in: rec_get_offsets(rec, index) */ + mem_heap_t* heap) /*!< in: memory heap from which + the memory needed is allocated */ + MY_ATTRIBUTE((warn_unused_result)); +/*******************************************************************//** +Converts an index record to a typed data tuple. NOTE that externally +stored (often big) fields are NOT copied to heap. +@return own: index entry built */ +dtuple_t* +row_rec_to_index_entry( +/*===================*/ + const rec_t* rec, /*!< in: record in the index */ + const dict_index_t* index, /*!< in: index */ + const rec_offs* offsets,/*!< in/out: rec_get_offsets(rec) */ + mem_heap_t* heap) /*!< in: memory heap from which + the memory needed is allocated */ + MY_ATTRIBUTE((warn_unused_result)); + +/** Convert a metadata record to a data tuple. +@param[in] rec metadata record +@param[in] index clustered index after instant ALTER TABLE +@param[in] offsets rec_get_offsets(rec) +@param[in,out] heap memory heap for allocations +@param[in] info_bits the info_bits after an update +@param[in] pad whether to pad to index->n_fields */ +dtuple_t* +row_metadata_to_tuple( + const rec_t* rec, + const dict_index_t* index, + const rec_offs* offsets, + mem_heap_t* heap, + ulint info_bits, + bool pad) + MY_ATTRIBUTE((nonnull,warn_unused_result)); + +/*******************************************************************//** +Builds from a secondary index record a row reference with which we can +search the clustered index record. +@return own: row reference built; see the NOTE below! */ +dtuple_t* +row_build_row_ref( +/*==============*/ + ulint type, /*!< in: ROW_COPY_DATA, or ROW_COPY_POINTERS: + the former copies also the data fields to + heap, whereas the latter only places pointers + to data fields on the index page */ + dict_index_t* index, /*!< in: secondary index */ + const rec_t* rec, /*!< in: record in the index; + NOTE: in the case ROW_COPY_POINTERS + the data fields in the row will point + directly into this record, therefore, + the buffer page of this record must be + at least s-latched and the latch held + as long as the row reference is used! */ + mem_heap_t* heap) /*!< in: memory heap from which the memory + needed is allocated */ + MY_ATTRIBUTE((warn_unused_result)); +/*******************************************************************//** +Builds from a secondary index record a row reference with which we can +search the clustered index record. */ +void +row_build_row_ref_in_tuple( +/*=======================*/ + dtuple_t* ref, /*!< in/out: row reference built; + see the NOTE below! */ + const rec_t* rec, /*!< in: record in the index; + NOTE: the data fields in ref + will point directly into this + record, therefore, the buffer + page of this record must be at + least s-latched and the latch + held as long as the row + reference is used! */ + const dict_index_t* index, /*!< in: secondary index */ + rec_offs* offsets)/*!< in: rec_get_offsets(rec, index) + or NULL */ + MY_ATTRIBUTE((nonnull(1,2,3))); +/*******************************************************************//** +Builds from a secondary index record a row reference with which we can +search the clustered index record. */ +UNIV_INLINE +void +row_build_row_ref_fast( +/*===================*/ + dtuple_t* ref, /*!< in/out: typed data tuple where the + reference is built */ + const ulint* map, /*!< in: array of field numbers in rec + telling how ref should be built from + the fields of rec */ + const rec_t* rec, /*!< in: secondary index record; + must be preserved while ref is used, as we do + not copy field values to heap */ + const rec_offs* offsets);/*!< in: array returned by rec_get_offsets() */ +/***************************************************************//** +Searches the clustered index record for a row, if we have the row +reference. +@return true if found */ +bool +row_search_on_row_ref( +/*==================*/ + btr_pcur_t* pcur, /*!< out: persistent cursor, which must + be closed by the caller */ + btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF, ... */ + const dict_table_t* table, /*!< in: table */ + const dtuple_t* ref, /*!< in: row reference */ + mtr_t* mtr) /*!< in/out: mtr */ + MY_ATTRIBUTE((nonnull, warn_unused_result)); +/*********************************************************************//** +Fetches the clustered index record for a secondary index record. The latches +on the secondary index record are preserved. +@return record or NULL, if no record found */ +rec_t* +row_get_clust_rec( +/*==============*/ + btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF, ... */ + const rec_t* rec, /*!< in: record in a secondary index */ + dict_index_t* index, /*!< in: secondary index */ + dict_index_t** clust_index,/*!< out: clustered index */ + mtr_t* mtr) /*!< in: mtr */ + MY_ATTRIBUTE((nonnull, warn_unused_result)); + +/** Parse the integer data from specified data, which could be +DATA_INT, DATA_FLOAT or DATA_DOUBLE. If the value is less than 0 +and the type is not unsigned then we reset the value to 0 +@param[in] data data to read +@param[in] len length of data +@param[in] mtype mtype of data +@param[in] unsigned_type if the data is unsigned +@return the integer value from the data */ +inline +ib_uint64_t +row_parse_int( + const byte* data, + ulint len, + ulint mtype, + bool unsigned_type); + +/** Result of row_search_index_entry */ +enum row_search_result { + ROW_FOUND = 0, /*!< the record was found */ + ROW_NOT_FOUND, /*!< record not found */ + ROW_BUFFERED, /*!< one of BTR_INSERT, BTR_DELETE, or + BTR_DELETE_MARK was specified, the + secondary index leaf page was not in + the buffer pool, and the operation was + enqueued in the insert/delete buffer */ + ROW_NOT_DELETED_REF /*!< BTR_DELETE was specified, and + row_purge_poss_sec() failed */ +}; + +/***************************************************************//** +Searches an index record. +@return whether the record was found or buffered */ +enum row_search_result +row_search_index_entry( +/*===================*/ + const dtuple_t* entry, /*!< in: index entry */ + btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF, ... */ + btr_pcur_t* pcur, /*!< in/out: persistent cursor, which must + be closed by the caller */ + mtr_t* mtr) /*!< in: mtr */ + MY_ATTRIBUTE((nonnull, warn_unused_result)); + +#define ROW_COPY_DATA 1 +#define ROW_COPY_POINTERS 2 + +/* The allowed latching order of index records is the following: +(1) a secondary index record -> +(2) the clustered index record -> +(3) rollback segment data for the clustered index record. */ + +/*******************************************************************//** +Formats the raw data in "data" (in InnoDB on-disk format) using +"dict_field" and writes the result to "buf". +Not more than "buf_size" bytes are written to "buf". +The result is always NUL-terminated (provided buf_size is positive) and the +number of bytes that were written to "buf" is returned (including the +terminating NUL). +@return number of bytes that were written */ +ulint +row_raw_format( +/*===========*/ + const char* data, /*!< in: raw data */ + ulint data_len, /*!< in: raw data length + in bytes */ + const dict_field_t* dict_field, /*!< in: index field */ + char* buf, /*!< out: output buffer */ + ulint buf_size) /*!< in: output buffer size + in bytes */ + MY_ATTRIBUTE((nonnull, warn_unused_result)); + +/** Prepare to start a mini-transaction to modify an index. +@param[in,out] mtr mini-transaction +@param[in,out] index possibly secondary index +@param[in] pessimistic whether this is a pessimistic operation */ +inline +void +row_mtr_start(mtr_t* mtr, dict_index_t* index, bool pessimistic) +{ + mtr->start(); + + switch (index->table->space_id) { + case IBUF_SPACE_ID: + if (pessimistic + && !(index->type & (DICT_UNIQUE | DICT_SPATIAL))) { + ibuf_free_excess_pages(); + } + break; + case SRV_TMP_SPACE_ID: + mtr->set_log_mode(MTR_LOG_NO_REDO); + break; + default: + index->set_modified(*mtr); + break; + } + + log_free_check(); +} + +#include "row0row.inl" + +#endif |