1 /***************************************************************************** 2 3 Copyright (c) 1996, 2021, Oracle and/or its affiliates. 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License, version 2.0, 7 as published by the Free Software Foundation. 8 9 This program is also distributed with certain software (including 10 but not limited to OpenSSL) that is licensed under separate terms, 11 as designated in a particular file or component or in included license 12 documentation. The authors of MySQL hereby grant you an additional 13 permission to link the program and your derivative works with the 14 separately licensed software that they have included with MySQL. 15 16 This program is distributed in the hope that it will be useful, 17 but WITHOUT ANY WARRANTY; without even the implied warranty of 18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 GNU General Public License, version 2.0, for more details. 20 21 You should have received a copy of the GNU General Public License along with 22 this program; if not, write to the Free Software Foundation, Inc., 23 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA 24 25 *****************************************************************************/ 26 27 /**************************************************//** 28 @file include/row0row.h 29 General row routines 30 31 Created 4/20/1996 Heikki Tuuri 32 *******************************************************/ 33 34 #ifndef row0row_h 35 #define row0row_h 36 37 #include "univ.i" 38 #include "data0data.h" 39 #include "dict0types.h" 40 #include "trx0types.h" 41 #include "que0types.h" 42 #include "mtr0mtr.h" 43 #include "rem0types.h" 44 #include "row0types.h" 45 #include "btr0types.h" 46 47 /*********************************************************************//** 48 Gets the offset of the DB_TRX_ID field, in bytes relative to the origin of 49 a clustered index record. 50 @return offset of DATA_TRX_ID */ 51 UNIV_INLINE 52 ulint 53 row_get_trx_id_offset( 54 /*==================*/ 55 const dict_index_t* index, /*!< in: clustered index */ 56 const ulint* offsets)/*!< in: record offsets */ 57 MY_ATTRIBUTE((warn_unused_result)); 58 /*********************************************************************//** 59 Reads the trx id field from a clustered index record. 60 @return value of the field */ 61 UNIV_INLINE 62 trx_id_t 63 row_get_rec_trx_id( 64 /*===============*/ 65 const rec_t* rec, /*!< in: record */ 66 const dict_index_t* index, /*!< in: clustered index */ 67 const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */ 68 MY_ATTRIBUTE((warn_unused_result)); 69 /*********************************************************************//** 70 Reads the roll pointer field from a clustered index record. 71 @return value of the field */ 72 UNIV_INLINE 73 roll_ptr_t 74 row_get_rec_roll_ptr( 75 /*=================*/ 76 const rec_t* rec, /*!< in: record */ 77 const dict_index_t* index, /*!< in: clustered index */ 78 const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */ 79 MY_ATTRIBUTE((warn_unused_result)); 80 81 /* Flags for row build type. */ 82 #define ROW_BUILD_NORMAL 0 /*!< build index row */ 83 #define ROW_BUILD_FOR_PURGE 1 /*!< build row for purge. */ 84 #define ROW_BUILD_FOR_UNDO 2 /*!< build row for undo. */ 85 #define ROW_BUILD_FOR_INSERT 3 /*!< build row for insert. */ 86 /*****************************************************************//** 87 When an insert or purge to a table is performed, this function builds 88 the entry to be inserted into or purged from an index on the table. 89 @return index entry which should be inserted or purged 90 @retval NULL if the externally stored columns in the clustered index record 91 are unavailable and ext != NULL, or row is missing some needed columns. */ 92 dtuple_t* 93 row_build_index_entry_low( 94 /*======================*/ 95 const dtuple_t* row, /*!< in: row which should be 96 inserted or purged */ 97 const row_ext_t* ext, /*!< in: externally stored column 98 prefixes, or NULL */ 99 dict_index_t* index, /*!< in: index on the table */ 100 mem_heap_t* heap, /*!< in: memory heap from which 101 the memory for the index entry 102 is allocated */ 103 ulint flag) /*!< in: ROW_BUILD_NORMAL, 104 ROW_BUILD_FOR_PURGE 105 or ROW_BUILD_FOR_UNDO */ 106 MY_ATTRIBUTE((warn_unused_result)); 107 /*****************************************************************//** 108 When an insert or purge to a table is performed, this function builds 109 the entry to be inserted into or purged from an index on the table. 110 @return index entry which should be inserted or purged, or NULL if the 111 externally stored columns in the clustered index record are 112 unavailable and ext != NULL */ 113 UNIV_INLINE 114 dtuple_t* 115 row_build_index_entry( 116 /*==================*/ 117 const dtuple_t* row, /*!< in: row which should be 118 inserted or purged */ 119 const row_ext_t* ext, /*!< in: externally stored column 120 prefixes, or NULL */ 121 dict_index_t* index, /*!< in: index on the table */ 122 mem_heap_t* heap) /*!< in: memory heap from which 123 the memory for the index entry 124 is allocated */ 125 MY_ATTRIBUTE((warn_unused_result)); 126 /*******************************************************************//** 127 An inverse function to row_build_index_entry. Builds a row from a 128 record in a clustered index. 129 @return own: row built; see the NOTE below! */ 130 dtuple_t* 131 row_build( 132 /*======*/ 133 ulint type, /*!< in: ROW_COPY_POINTERS or 134 ROW_COPY_DATA; the latter 135 copies also the data fields to 136 heap while the first only 137 places pointers to data fields 138 on the index page, and thus is 139 more efficient */ 140 const dict_index_t* index, /*!< in: clustered index */ 141 const rec_t* rec, /*!< in: record in the clustered 142 index; NOTE: in the case 143 ROW_COPY_POINTERS the data 144 fields in the row will point 145 directly into this record, 146 therefore, the buffer page of 147 this record must be at least 148 s-latched and the latch held 149 as long as the row dtuple is used! */ 150 const ulint* offsets,/*!< in: rec_get_offsets(rec,index) 151 or NULL, in which case this function 152 will invoke rec_get_offsets() */ 153 const dict_table_t* col_table, 154 /*!< in: table, to check which 155 externally stored columns 156 occur in the ordering columns 157 of an index, or NULL if 158 index->table should be 159 consulted instead; the user 160 columns in this table should be 161 the same columns as in index->table */ 162 const dtuple_t* add_cols, 163 /*!< in: default values of 164 added columns, or NULL */ 165 const ulint* col_map,/*!< in: mapping of old column 166 numbers to new ones, or NULL */ 167 row_ext_t** ext, /*!< out, own: cache of 168 externally stored column 169 prefixes, or NULL */ 170 mem_heap_t* heap); /*!< in: memory heap from which 171 the memory needed is allocated */ 172 173 /** An inverse function to row_build_index_entry. Builds a row from a 174 record in a clustered index, with possible indexing on ongoing 175 addition of new virtual columns. 176 @param[in] type ROW_COPY_POINTERS or ROW_COPY_DATA; 177 @param[in] index clustered index 178 @param[in] rec record in the clustered index 179 @param[in] offsets rec_get_offsets(rec,index) or NULL 180 @param[in] col_table table, to check which 181 externally stored columns 182 occur in the ordering columns 183 of an index, or NULL if 184 index->table should be 185 consulted instead 186 @param[in] add_cols default values of added columns, or NULL 187 @param[in] add_v new virtual columns added 188 along with new indexes 189 @param[in] col_map mapping of old column 190 numbers to new ones, or NULL 191 @param[in] ext cache of externally stored column 192 prefixes, or NULL 193 @param[in] heap memory heap from which 194 the memory needed is allocated 195 @return own: row built */ 196 dtuple_t* 197 row_build_w_add_vcol( 198 ulint type, 199 const dict_index_t* index, 200 const rec_t* rec, 201 const ulint* offsets, 202 const dict_table_t* col_table, 203 const dtuple_t* add_cols, 204 const dict_add_v_col_t* add_v, 205 const ulint* col_map, 206 row_ext_t** ext, 207 mem_heap_t* heap); 208 209 /*******************************************************************//** 210 Converts an index record to a typed data tuple. 211 @return index entry built; does not set info_bits, and the data fields 212 in the entry will point directly to rec */ 213 dtuple_t* 214 row_rec_to_index_entry_low( 215 /*=======================*/ 216 const rec_t* rec, /*!< in: record in the index */ 217 const dict_index_t* index, /*!< in: index */ 218 const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */ 219 ulint* n_ext, /*!< out: number of externally 220 stored columns */ 221 mem_heap_t* heap) /*!< in: memory heap from which 222 the memory needed is allocated */ 223 MY_ATTRIBUTE((warn_unused_result)); 224 /*******************************************************************//** 225 Converts an index record to a typed data tuple. NOTE that externally 226 stored (often big) fields are NOT copied to heap. 227 @return own: index entry built */ 228 dtuple_t* 229 row_rec_to_index_entry( 230 /*===================*/ 231 const rec_t* rec, /*!< in: record in the index */ 232 const dict_index_t* index, /*!< in: index */ 233 const ulint* offsets,/*!< in/out: rec_get_offsets(rec) */ 234 ulint* n_ext, /*!< out: number of externally 235 stored columns */ 236 mem_heap_t* heap) /*!< in: memory heap from which 237 the memory needed is allocated */ 238 MY_ATTRIBUTE((warn_unused_result)); 239 /*******************************************************************//** 240 Builds from a secondary index record a row reference with which we can 241 search the clustered index record. 242 @return own: row reference built; see the NOTE below! */ 243 dtuple_t* 244 row_build_row_ref( 245 /*==============*/ 246 ulint type, /*!< in: ROW_COPY_DATA, or ROW_COPY_POINTERS: 247 the former copies also the data fields to 248 heap, whereas the latter only places pointers 249 to data fields on the index page */ 250 dict_index_t* index, /*!< in: secondary index */ 251 const rec_t* rec, /*!< in: record in the index; 252 NOTE: in the case ROW_COPY_POINTERS 253 the data fields in the row will point 254 directly into this record, therefore, 255 the buffer page of this record must be 256 at least s-latched and the latch held 257 as long as the row reference is used! */ 258 mem_heap_t* heap) /*!< in: memory heap from which the memory 259 needed is allocated */ 260 MY_ATTRIBUTE((warn_unused_result)); 261 /*******************************************************************//** 262 Builds from a secondary index record a row reference with which we can 263 search the clustered index record. */ 264 void 265 row_build_row_ref_in_tuple( 266 /*=======================*/ 267 dtuple_t* ref, /*!< in/out: row reference built; 268 see the NOTE below! */ 269 const rec_t* rec, /*!< in: record in the index; 270 NOTE: the data fields in ref 271 will point directly into this 272 record, therefore, the buffer 273 page of this record must be at 274 least s-latched and the latch 275 held as long as the row 276 reference is used! */ 277 const dict_index_t* index, /*!< in: secondary index */ 278 ulint* offsets,/*!< in: rec_get_offsets(rec, index) 279 or NULL */ 280 trx_t* trx); /*!< in: transaction or NULL */ 281 282 /*******************************************************************//** 283 Builds from a secondary index record a row reference with which we can 284 search the clustered index record. */ 285 UNIV_INLINE 286 void 287 row_build_row_ref_fast( 288 /*===================*/ 289 dtuple_t* ref, /*!< in/out: typed data tuple where the 290 reference is built */ 291 const ulint* map, /*!< in: array of field numbers in rec 292 telling how ref should be built from 293 the fields of rec */ 294 const rec_t* rec, /*!< in: record in the index; must be 295 preserved while ref is used, as we do 296 not copy field values to heap */ 297 const ulint* offsets);/*!< in: array returned by rec_get_offsets() */ 298 /***************************************************************//** 299 Searches the clustered index record for a row, if we have the row 300 reference. 301 @return TRUE if found */ 302 ibool 303 row_search_on_row_ref( 304 /*==================*/ 305 btr_pcur_t* pcur, /*!< out: persistent cursor, which must 306 be closed by the caller */ 307 ulint mode, /*!< in: BTR_MODIFY_LEAF, ... */ 308 const dict_table_t* table, /*!< in: table */ 309 const dtuple_t* ref, /*!< in: row reference */ 310 mtr_t* mtr) /*!< in/out: mtr */ 311 MY_ATTRIBUTE((warn_unused_result)); 312 /*********************************************************************//** 313 Fetches the clustered index record for a secondary index record. The latches 314 on the secondary index record are preserved. 315 @return record or NULL, if no record found */ 316 rec_t* 317 row_get_clust_rec( 318 /*==============*/ 319 ulint mode, /*!< in: BTR_MODIFY_LEAF, ... */ 320 const rec_t* rec, /*!< in: record in a secondary index */ 321 dict_index_t* index, /*!< in: secondary index */ 322 dict_index_t** clust_index,/*!< out: clustered index */ 323 mtr_t* mtr) /*!< in: mtr */ 324 MY_ATTRIBUTE((warn_unused_result)); 325 326 /** Result of row_search_index_entry */ 327 enum row_search_result { 328 ROW_FOUND = 0, /*!< the record was found */ 329 ROW_NOT_FOUND, /*!< record not found */ 330 ROW_BUFFERED, /*!< one of BTR_INSERT, BTR_DELETE, or 331 BTR_DELETE_MARK was specified, the 332 secondary index leaf page was not in 333 the buffer pool, and the operation was 334 enqueued in the insert/delete buffer */ 335 ROW_NOT_DELETED_REF /*!< BTR_DELETE was specified, and 336 row_purge_poss_sec() failed */ 337 }; 338 339 /***************************************************************//** 340 Searches an index record. 341 @return whether the record was found or buffered */ 342 enum row_search_result 343 row_search_index_entry( 344 /*===================*/ 345 dict_index_t* index, /*!< in: index */ 346 const dtuple_t* entry, /*!< in: index entry */ 347 ulint mode, /*!< in: BTR_MODIFY_LEAF, ... */ 348 btr_pcur_t* pcur, /*!< in/out: persistent cursor, which must 349 be closed by the caller */ 350 mtr_t* mtr) /*!< in: mtr */ 351 MY_ATTRIBUTE((warn_unused_result)); 352 353 #define ROW_COPY_DATA 1 354 #define ROW_COPY_POINTERS 2 355 356 /* The allowed latching order of index records is the following: 357 (1) a secondary index record -> 358 (2) the clustered index record -> 359 (3) rollback segment data for the clustered index record. */ 360 361 /*******************************************************************//** 362 Formats the raw data in "data" (in InnoDB on-disk format) using 363 "dict_field" and writes the result to "buf". 364 Not more than "buf_size" bytes are written to "buf". 365 The result is always NUL-terminated (provided buf_size is positive) and the 366 number of bytes that were written to "buf" is returned (including the 367 terminating NUL). 368 @return number of bytes that were written */ 369 ulint 370 row_raw_format( 371 /*===========*/ 372 const char* data, /*!< in: raw data */ 373 ulint data_len, /*!< in: raw data length 374 in bytes */ 375 const dict_field_t* dict_field, /*!< in: index field */ 376 char* buf, /*!< out: output buffer */ 377 ulint buf_size) /*!< in: output buffer size 378 in bytes */ 379 MY_ATTRIBUTE((warn_unused_result)); 380 381 #ifndef UNIV_NONINL 382 #include "row0row.ic" 383 #endif 384 385 #endif 386