1 /***************************************************************************** 2 3 Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. 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 "read0types.h" 45 #include "row0types.h" 46 #include "btr0types.h" 47 48 /*********************************************************************//** 49 Gets the offset of the DB_TRX_ID field, in bytes relative to the origin of 50 a clustered index record. 51 @return offset of DATA_TRX_ID */ 52 UNIV_INLINE 53 ulint 54 row_get_trx_id_offset( 55 /*==================*/ 56 const dict_index_t* index, /*!< in: clustered index */ 57 const ulint* offsets)/*!< in: record offsets */ 58 MY_ATTRIBUTE((nonnull, warn_unused_result)); 59 /*********************************************************************//** 60 Reads the trx id field from a clustered index record. 61 @return value of the field */ 62 UNIV_INLINE 63 trx_id_t 64 row_get_rec_trx_id( 65 /*===============*/ 66 const rec_t* rec, /*!< in: record */ 67 const dict_index_t* index, /*!< in: clustered index */ 68 const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */ 69 MY_ATTRIBUTE((nonnull, warn_unused_result)); 70 /*********************************************************************//** 71 Reads the roll pointer field from a clustered index record. 72 @return value of the field */ 73 UNIV_INLINE 74 roll_ptr_t 75 row_get_rec_roll_ptr( 76 /*=================*/ 77 const rec_t* rec, /*!< in: record */ 78 const dict_index_t* index, /*!< in: clustered index */ 79 const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */ 80 MY_ATTRIBUTE((nonnull, warn_unused_result)); 81 /*****************************************************************//** 82 When an insert or purge to a table is performed, this function builds 83 the entry to be inserted into or purged from an index on the table. 84 @return index entry which should be inserted or purged 85 @retval NULL if the externally stored columns in the clustered index record 86 are unavailable and ext != NULL, or row is missing some needed columns. */ 87 UNIV_INTERN 88 dtuple_t* 89 row_build_index_entry_low( 90 /*======================*/ 91 const dtuple_t* row, /*!< in: row which should be 92 inserted or purged */ 93 const row_ext_t* ext, /*!< in: externally stored column 94 prefixes, or NULL */ 95 dict_index_t* index, /*!< in: index on the table */ 96 mem_heap_t* heap) /*!< in: memory heap from which 97 the memory for the index entry 98 is allocated */ 99 MY_ATTRIBUTE((warn_unused_result, nonnull(1,3,4))); 100 /*****************************************************************//** 101 When an insert or purge to a table is performed, this function builds 102 the entry to be inserted into or purged from an index on the table. 103 @return index entry which should be inserted or purged, or NULL if the 104 externally stored columns in the clustered index record are 105 unavailable and ext != NULL */ 106 UNIV_INLINE 107 dtuple_t* 108 row_build_index_entry( 109 /*==================*/ 110 const dtuple_t* row, /*!< in: row which should be 111 inserted or purged */ 112 const row_ext_t* ext, /*!< in: externally stored column 113 prefixes, or NULL */ 114 dict_index_t* index, /*!< in: index on the table */ 115 mem_heap_t* heap) /*!< in: memory heap from which 116 the memory for the index entry 117 is allocated */ 118 MY_ATTRIBUTE((warn_unused_result, nonnull(1,3,4))); 119 /*******************************************************************//** 120 An inverse function to row_build_index_entry. Builds a row from a 121 record in a clustered index. 122 @return own: row built; see the NOTE below! */ 123 UNIV_INTERN 124 dtuple_t* 125 row_build( 126 /*======*/ 127 ulint type, /*!< in: ROW_COPY_POINTERS or 128 ROW_COPY_DATA; the latter 129 copies also the data fields to 130 heap while the first only 131 places pointers to data fields 132 on the index page, and thus is 133 more efficient */ 134 const dict_index_t* index, /*!< in: clustered index */ 135 const rec_t* rec, /*!< in: record in the clustered 136 index; NOTE: in the case 137 ROW_COPY_POINTERS the data 138 fields in the row will point 139 directly into this record, 140 therefore, the buffer page of 141 this record must be at least 142 s-latched and the latch held 143 as long as the row dtuple is used! */ 144 const ulint* offsets,/*!< in: rec_get_offsets(rec,index) 145 or NULL, in which case this function 146 will invoke rec_get_offsets() */ 147 const dict_table_t* col_table, 148 /*!< in: table, to check which 149 externally stored columns 150 occur in the ordering columns 151 of an index, or NULL if 152 index->table should be 153 consulted instead; the user 154 columns in this table should be 155 the same columns as in index->table */ 156 const dtuple_t* add_cols, 157 /*!< in: default values of 158 added columns, or NULL */ 159 const ulint* col_map,/*!< in: mapping of old column 160 numbers to new ones, or NULL */ 161 row_ext_t** ext, /*!< out, own: cache of 162 externally stored column 163 prefixes, or NULL */ 164 mem_heap_t* heap) /*!< in: memory heap from which 165 the memory needed is allocated */ 166 MY_ATTRIBUTE((nonnull(2,3,9))); 167 /*******************************************************************//** 168 Converts an index record to a typed data tuple. 169 @return index entry built; does not set info_bits, and the data fields 170 in the entry will point directly to rec */ 171 UNIV_INTERN 172 dtuple_t* 173 row_rec_to_index_entry_low( 174 /*=======================*/ 175 const rec_t* rec, /*!< in: record in the index */ 176 const dict_index_t* index, /*!< in: index */ 177 const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */ 178 ulint* n_ext, /*!< out: number of externally 179 stored columns */ 180 mem_heap_t* heap) /*!< in: memory heap from which 181 the memory needed is allocated */ 182 MY_ATTRIBUTE((nonnull, warn_unused_result)); 183 /*******************************************************************//** 184 Converts an index record to a typed data tuple. NOTE that externally 185 stored (often big) fields are NOT copied to heap. 186 @return own: index entry built */ 187 UNIV_INTERN 188 dtuple_t* 189 row_rec_to_index_entry( 190 /*===================*/ 191 const rec_t* rec, /*!< in: record in the index */ 192 const dict_index_t* index, /*!< in: index */ 193 const ulint* offsets,/*!< in/out: rec_get_offsets(rec) */ 194 ulint* n_ext, /*!< out: number of externally 195 stored columns */ 196 mem_heap_t* heap) /*!< in: memory heap from which 197 the memory needed is allocated */ 198 MY_ATTRIBUTE((nonnull, warn_unused_result)); 199 /*******************************************************************//** 200 Builds from a secondary index record a row reference with which we can 201 search the clustered index record. 202 @return own: row reference built; see the NOTE below! */ 203 UNIV_INTERN 204 dtuple_t* 205 row_build_row_ref( 206 /*==============*/ 207 ulint type, /*!< in: ROW_COPY_DATA, or ROW_COPY_POINTERS: 208 the former copies also the data fields to 209 heap, whereas the latter only places pointers 210 to data fields on the index page */ 211 dict_index_t* index, /*!< in: secondary index */ 212 const rec_t* rec, /*!< in: record in the index; 213 NOTE: in the case ROW_COPY_POINTERS 214 the data fields in the row will point 215 directly into this record, therefore, 216 the buffer page of this record must be 217 at least s-latched and the latch held 218 as long as the row reference is used! */ 219 mem_heap_t* heap) /*!< in: memory heap from which the memory 220 needed is allocated */ 221 MY_ATTRIBUTE((nonnull, warn_unused_result)); 222 /*******************************************************************//** 223 Builds from a secondary index record a row reference with which we can 224 search the clustered index record. */ 225 UNIV_INTERN 226 void 227 row_build_row_ref_in_tuple( 228 /*=======================*/ 229 dtuple_t* ref, /*!< in/out: row reference built; 230 see the NOTE below! */ 231 const rec_t* rec, /*!< in: record in the index; 232 NOTE: the data fields in ref 233 will point directly into this 234 record, therefore, the buffer 235 page of this record must be at 236 least s-latched and the latch 237 held as long as the row 238 reference is used! */ 239 const dict_index_t* index, /*!< in: secondary index */ 240 ulint* offsets,/*!< in: rec_get_offsets(rec, index) 241 or NULL */ 242 trx_t* trx) /*!< in: transaction or NULL */ 243 MY_ATTRIBUTE((nonnull(1,2,3))); 244 /*******************************************************************//** 245 Builds from a secondary index record a row reference with which we can 246 search the clustered index record. */ 247 UNIV_INLINE 248 void 249 row_build_row_ref_fast( 250 /*===================*/ 251 dtuple_t* ref, /*!< in/out: typed data tuple where the 252 reference is built */ 253 const ulint* map, /*!< in: array of field numbers in rec 254 telling how ref should be built from 255 the fields of rec */ 256 const rec_t* rec, /*!< in: record in the index; must be 257 preserved while ref is used, as we do 258 not copy field values to heap */ 259 const ulint* offsets);/*!< in: array returned by rec_get_offsets() */ 260 /***************************************************************//** 261 Searches the clustered index record for a row, if we have the row 262 reference. 263 @return TRUE if found */ 264 UNIV_INTERN 265 ibool 266 row_search_on_row_ref( 267 /*==================*/ 268 btr_pcur_t* pcur, /*!< out: persistent cursor, which must 269 be closed by the caller */ 270 ulint mode, /*!< in: BTR_MODIFY_LEAF, ... */ 271 const dict_table_t* table, /*!< in: table */ 272 const dtuple_t* ref, /*!< in: row reference */ 273 mtr_t* mtr) /*!< in/out: mtr */ 274 MY_ATTRIBUTE((nonnull, warn_unused_result)); 275 /*********************************************************************//** 276 Fetches the clustered index record for a secondary index record. The latches 277 on the secondary index record are preserved. 278 @return record or NULL, if no record found */ 279 UNIV_INTERN 280 rec_t* 281 row_get_clust_rec( 282 /*==============*/ 283 ulint mode, /*!< in: BTR_MODIFY_LEAF, ... */ 284 const rec_t* rec, /*!< in: record in a secondary index */ 285 dict_index_t* index, /*!< in: secondary index */ 286 dict_index_t** clust_index,/*!< out: clustered index */ 287 mtr_t* mtr) /*!< in: mtr */ 288 MY_ATTRIBUTE((nonnull, warn_unused_result)); 289 290 /** Result of row_search_index_entry */ 291 enum row_search_result { 292 ROW_FOUND = 0, /*!< the record was found */ 293 ROW_NOT_FOUND, /*!< record not found */ 294 ROW_BUFFERED, /*!< one of BTR_INSERT, BTR_DELETE, or 295 BTR_DELETE_MARK was specified, the 296 secondary index leaf page was not in 297 the buffer pool, and the operation was 298 enqueued in the insert/delete buffer */ 299 ROW_NOT_DELETED_REF /*!< BTR_DELETE was specified, and 300 row_purge_poss_sec() failed */ 301 }; 302 303 /***************************************************************//** 304 Searches an index record. 305 @return whether the record was found or buffered */ 306 UNIV_INTERN 307 enum row_search_result 308 row_search_index_entry( 309 /*===================*/ 310 dict_index_t* index, /*!< in: index */ 311 const dtuple_t* entry, /*!< in: index entry */ 312 ulint mode, /*!< in: BTR_MODIFY_LEAF, ... */ 313 btr_pcur_t* pcur, /*!< in/out: persistent cursor, which must 314 be closed by the caller */ 315 mtr_t* mtr) /*!< in: mtr */ 316 MY_ATTRIBUTE((nonnull, warn_unused_result)); 317 318 #define ROW_COPY_DATA 1 319 #define ROW_COPY_POINTERS 2 320 321 /* The allowed latching order of index records is the following: 322 (1) a secondary index record -> 323 (2) the clustered index record -> 324 (3) rollback segment data for the clustered index record. */ 325 326 /*******************************************************************//** 327 Formats the raw data in "data" (in InnoDB on-disk format) using 328 "dict_field" and writes the result to "buf". 329 Not more than "buf_size" bytes are written to "buf". 330 The result is always NUL-terminated (provided buf_size is positive) and the 331 number of bytes that were written to "buf" is returned (including the 332 terminating NUL). 333 @return number of bytes that were written */ 334 UNIV_INTERN 335 ulint 336 row_raw_format( 337 /*===========*/ 338 const char* data, /*!< in: raw data */ 339 ulint data_len, /*!< in: raw data length 340 in bytes */ 341 const dict_field_t* dict_field, /*!< in: index field */ 342 char* buf, /*!< out: output buffer */ 343 ulint buf_size) /*!< in: output buffer size 344 in bytes */ 345 MY_ATTRIBUTE((nonnull, warn_unused_result)); 346 347 #ifndef UNIV_NONINL 348 #include "row0row.ic" 349 #endif 350 351 #endif 352