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/row0upd.h 29 Update of a row 30 31 Created 12/27/1996 Heikki Tuuri 32 *******************************************************/ 33 34 #ifndef row0upd_h 35 #define row0upd_h 36 37 #include "univ.i" 38 #include "data0data.h" 39 #include "row0types.h" 40 #include "btr0types.h" 41 #include "dict0types.h" 42 #include "trx0types.h" 43 44 #ifndef UNIV_HOTBACKUP 45 # include "btr0pcur.h" 46 # include "que0types.h" 47 # include "pars0types.h" 48 #endif /* !UNIV_HOTBACKUP */ 49 50 /*********************************************************************//** 51 Creates an update vector object. 52 @return own: update vector object */ 53 UNIV_INLINE 54 upd_t* 55 upd_create( 56 /*=======*/ 57 ulint n, /*!< in: number of fields */ 58 mem_heap_t* heap); /*!< in: heap from which memory allocated */ 59 /*********************************************************************//** 60 Returns the number of fields in the update vector == number of columns 61 to be updated by an update vector. 62 @return number of fields */ 63 UNIV_INLINE 64 ulint 65 upd_get_n_fields( 66 /*=============*/ 67 const upd_t* update); /*!< in: update vector */ 68 #ifdef UNIV_DEBUG 69 /*********************************************************************//** 70 Returns the nth field of an update vector. 71 @return update vector field */ 72 UNIV_INLINE 73 upd_field_t* 74 upd_get_nth_field( 75 /*==============*/ 76 const upd_t* update, /*!< in: update vector */ 77 ulint n); /*!< in: field position in update vector */ 78 #else 79 # define upd_get_nth_field(update, n) ((update)->fields + (n)) 80 #endif 81 #ifndef UNIV_HOTBACKUP 82 /*********************************************************************//** 83 Sets an index field number to be updated by an update vector field. */ 84 UNIV_INLINE 85 void 86 upd_field_set_field_no( 87 /*===================*/ 88 upd_field_t* upd_field, /*!< in: update vector field */ 89 ulint field_no, /*!< in: field number in a clustered 90 index */ 91 dict_index_t* index, /*!< in: index */ 92 trx_t* trx); /*!< in: transaction */ 93 /*********************************************************************//** 94 Returns a field of an update vector by field_no. 95 @return update vector field, or NULL */ 96 UNIV_INLINE 97 const upd_field_t* 98 upd_get_field_by_field_no( 99 /*======================*/ 100 const upd_t* update, /*!< in: update vector */ 101 ulint no) /*!< in: field_no */ 102 MY_ATTRIBUTE((nonnull, pure)); 103 /*********************************************************************//** 104 Writes into the redo log the values of trx id and roll ptr and enough info 105 to determine their positions within a clustered index record. 106 @return new pointer to mlog */ 107 UNIV_INTERN 108 byte* 109 row_upd_write_sys_vals_to_log( 110 /*==========================*/ 111 dict_index_t* index, /*!< in: clustered index */ 112 trx_id_t trx_id, /*!< in: transaction id */ 113 roll_ptr_t roll_ptr,/*!< in: roll ptr of the undo log record */ 114 byte* log_ptr,/*!< pointer to a buffer of size > 20 opened 115 in mlog */ 116 mtr_t* mtr); /*!< in: mtr */ 117 /*********************************************************************//** 118 Updates the trx id and roll ptr field in a clustered index record when 119 a row is updated or marked deleted. */ 120 UNIV_INLINE 121 void 122 row_upd_rec_sys_fields( 123 /*===================*/ 124 rec_t* rec, /*!< in/out: record */ 125 page_zip_des_t* page_zip,/*!< in/out: compressed page whose 126 uncompressed part will be updated, or NULL */ 127 dict_index_t* index, /*!< in: clustered index */ 128 const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */ 129 const trx_t* trx, /*!< in: transaction */ 130 roll_ptr_t roll_ptr);/*!< in: roll ptr of the undo log record, 131 can be 0 during IMPORT */ 132 /*********************************************************************//** 133 Sets the trx id or roll ptr field of a clustered index entry. */ 134 UNIV_INTERN 135 void 136 row_upd_index_entry_sys_field( 137 /*==========================*/ 138 dtuple_t* entry, /*!< in/out: index entry, where the memory 139 buffers for sys fields are already allocated: 140 the function just copies the new values to 141 them */ 142 dict_index_t* index, /*!< in: clustered index */ 143 ulint type, /*!< in: DATA_TRX_ID or DATA_ROLL_PTR */ 144 ib_uint64_t val); /*!< in: value to write */ 145 /*********************************************************************//** 146 Creates an update node for a query graph. 147 @return own: update node */ 148 UNIV_INTERN 149 upd_node_t* 150 upd_node_create( 151 /*============*/ 152 mem_heap_t* heap); /*!< in: mem heap where created */ 153 /***********************************************************//** 154 Writes to the redo log the new values of the fields occurring in the index. */ 155 UNIV_INTERN 156 void 157 row_upd_index_write_log( 158 /*====================*/ 159 const upd_t* update, /*!< in: update vector */ 160 byte* log_ptr,/*!< in: pointer to mlog buffer: must 161 contain at least MLOG_BUF_MARGIN bytes 162 of free space; the buffer is closed 163 within this function */ 164 mtr_t* mtr); /*!< in: mtr into whose log to write */ 165 /***********************************************************//** 166 Returns TRUE if row update changes size of some field in index or if some 167 field to be updated is stored externally in rec or update. 168 @return TRUE if the update changes the size of some field in index or 169 the field is external in rec or update */ 170 UNIV_INTERN 171 ibool 172 row_upd_changes_field_size_or_external( 173 /*===================================*/ 174 dict_index_t* index, /*!< in: index */ 175 const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */ 176 const upd_t* update);/*!< in: update vector */ 177 /***********************************************************//** 178 Returns true if row update contains disowned external fields. 179 @return true if the update contains disowned external fields. */ 180 UNIV_INTERN 181 bool 182 row_upd_changes_disowned_external( 183 /*==============================*/ 184 const upd_t* update) /*!< in: update vector */ 185 MY_ATTRIBUTE((nonnull, warn_unused_result)); 186 #endif /* !UNIV_HOTBACKUP */ 187 /***********************************************************//** 188 Replaces the new column values stored in the update vector to the 189 record given. No field size changes are allowed. This function is 190 usually invoked on a clustered index. The only use case for a 191 secondary index is row_ins_sec_index_entry_by_modify() or its 192 counterpart in ibuf_insert_to_index_page(). */ 193 UNIV_INTERN 194 void 195 row_upd_rec_in_place( 196 /*=================*/ 197 rec_t* rec, /*!< in/out: record where replaced */ 198 dict_index_t* index, /*!< in: the index the record belongs to */ 199 const ulint* offsets,/*!< in: array returned by rec_get_offsets() */ 200 const upd_t* update, /*!< in: update vector */ 201 page_zip_des_t* page_zip);/*!< in: compressed page with enough space 202 available, or NULL */ 203 #ifndef UNIV_HOTBACKUP 204 /***************************************************************//** 205 Builds an update vector from those fields which in a secondary index entry 206 differ from a record that has the equal ordering fields. NOTE: we compare 207 the fields as binary strings! 208 @return own: update vector of differing fields */ 209 UNIV_INTERN 210 upd_t* 211 row_upd_build_sec_rec_difference_binary( 212 /*====================================*/ 213 const rec_t* rec, /*!< in: secondary index record */ 214 dict_index_t* index, /*!< in: index */ 215 const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */ 216 const dtuple_t* entry, /*!< in: entry to insert */ 217 mem_heap_t* heap) /*!< in: memory heap from which allocated */ 218 MY_ATTRIBUTE((warn_unused_result, nonnull)); 219 /***************************************************************//** 220 Builds an update vector from those fields, excluding the roll ptr and 221 trx id fields, which in an index entry differ from a record that has 222 the equal ordering fields. NOTE: we compare the fields as binary strings! 223 @return own: update vector of differing fields, excluding roll ptr and 224 trx id */ 225 UNIV_INTERN 226 const upd_t* 227 row_upd_build_difference_binary( 228 /*============================*/ 229 dict_index_t* index, /*!< in: clustered index */ 230 const dtuple_t* entry, /*!< in: entry to insert */ 231 const rec_t* rec, /*!< in: clustered index record */ 232 const ulint* offsets,/*!< in: rec_get_offsets(rec,index), or NULL */ 233 bool no_sys, /*!< in: skip the system columns 234 DB_TRX_ID and DB_ROLL_PTR */ 235 trx_t* trx, /*!< in: transaction (for diagnostics), 236 or NULL */ 237 mem_heap_t* heap) /*!< in: memory heap from which allocated */ 238 MY_ATTRIBUTE((nonnull(1,2,3,7), warn_unused_result)); 239 /***********************************************************//** 240 Replaces the new column values stored in the update vector to the index entry 241 given. */ 242 UNIV_INTERN 243 void 244 row_upd_index_replace_new_col_vals_index_pos( 245 /*=========================================*/ 246 dtuple_t* entry, /*!< in/out: index entry where replaced; 247 the clustered index record must be 248 covered by a lock or a page latch to 249 prevent deletion (rollback or purge) */ 250 dict_index_t* index, /*!< in: index; NOTE that this may also be a 251 non-clustered index */ 252 const upd_t* update, /*!< in: an update vector built for the index so 253 that the field number in an upd_field is the 254 index position */ 255 ibool order_only, 256 /*!< in: if TRUE, limit the replacement to 257 ordering fields of index; note that this 258 does not work for non-clustered indexes. */ 259 mem_heap_t* heap) /*!< in: memory heap for allocating and 260 copying the new values */ 261 MY_ATTRIBUTE((nonnull)); 262 /***********************************************************//** 263 Replaces the new column values stored in the update vector to the index entry 264 given. */ 265 UNIV_INTERN 266 void 267 row_upd_index_replace_new_col_vals( 268 /*===============================*/ 269 dtuple_t* entry, /*!< in/out: index entry where replaced; 270 the clustered index record must be 271 covered by a lock or a page latch to 272 prevent deletion (rollback or purge) */ 273 dict_index_t* index, /*!< in: index; NOTE that this may also be a 274 non-clustered index */ 275 const upd_t* update, /*!< in: an update vector built for the 276 CLUSTERED index so that the field number in 277 an upd_field is the clustered index position */ 278 mem_heap_t* heap) /*!< in: memory heap for allocating and 279 copying the new values */ 280 MY_ATTRIBUTE((nonnull)); 281 /***********************************************************//** 282 Replaces the new column values stored in the update vector. */ 283 UNIV_INTERN 284 void 285 row_upd_replace( 286 /*============*/ 287 dtuple_t* row, /*!< in/out: row where replaced, 288 indexed by col_no; 289 the clustered index record must be 290 covered by a lock or a page latch to 291 prevent deletion (rollback or purge) */ 292 row_ext_t** ext, /*!< out, own: NULL, or externally 293 stored column prefixes */ 294 const dict_index_t* index, /*!< in: clustered index */ 295 const upd_t* update, /*!< in: an update vector built for the 296 clustered index */ 297 mem_heap_t* heap); /*!< in: memory heap */ 298 /***********************************************************//** 299 Checks if an update vector changes an ordering field of an index record. 300 301 This function is fast if the update vector is short or the number of ordering 302 fields in the index is small. Otherwise, this can be quadratic. 303 NOTE: we compare the fields as binary strings! 304 @return TRUE if update vector changes an ordering field in the index record */ 305 UNIV_INTERN 306 ibool 307 row_upd_changes_ord_field_binary_func( 308 /*==================================*/ 309 dict_index_t* index, /*!< in: index of the record */ 310 const upd_t* update, /*!< in: update vector for the row; NOTE: the 311 field numbers in this MUST be clustered index 312 positions! */ 313 #ifdef UNIV_DEBUG 314 const que_thr_t*thr, /*!< in: query thread */ 315 #endif /* UNIV_DEBUG */ 316 const dtuple_t* row, /*!< in: old value of row, or NULL if the 317 row and the data values in update are not 318 known when this function is called, e.g., at 319 compile time */ 320 const row_ext_t*ext) /*!< NULL, or prefixes of the externally 321 stored columns in the old row */ 322 MY_ATTRIBUTE((nonnull(1,2), warn_unused_result)); 323 #ifdef UNIV_DEBUG 324 # define row_upd_changes_ord_field_binary(index,update,thr,row,ext) \ 325 row_upd_changes_ord_field_binary_func(index,update,thr,row,ext) 326 #else /* UNIV_DEBUG */ 327 # define row_upd_changes_ord_field_binary(index,update,thr,row,ext) \ 328 row_upd_changes_ord_field_binary_func(index,update,row,ext) 329 #endif /* UNIV_DEBUG */ 330 /***********************************************************//** 331 Checks if an FTS indexed column is affected by an UPDATE. 332 @return offset within fts_t::indexes if FTS indexed column updated else 333 ULINT_UNDEFINED */ 334 UNIV_INTERN 335 ulint 336 row_upd_changes_fts_column( 337 /*=======================*/ 338 dict_table_t* table, /*!< in: table */ 339 upd_field_t* upd_field); /*!< in: field to check */ 340 /***********************************************************//** 341 Checks if an FTS Doc ID column is affected by an UPDATE. 342 @return whether Doc ID column is affected */ 343 UNIV_INTERN 344 bool 345 row_upd_changes_doc_id( 346 /*===================*/ 347 dict_table_t* table, /*!< in: table */ 348 upd_field_t* upd_field) /*!< in: field to check */ 349 MY_ATTRIBUTE((nonnull, warn_unused_result)); 350 /***********************************************************//** 351 Checks if an update vector changes an ordering field of an index record. 352 This function is fast if the update vector is short or the number of ordering 353 fields in the index is small. Otherwise, this can be quadratic. 354 NOTE: we compare the fields as binary strings! 355 @return TRUE if update vector may change an ordering field in an index 356 record */ 357 UNIV_INTERN 358 ibool 359 row_upd_changes_some_index_ord_field_binary( 360 /*========================================*/ 361 const dict_table_t* table, /*!< in: table */ 362 const upd_t* update);/*!< in: update vector for the row */ 363 /***********************************************************//** 364 Updates a row in a table. This is a high-level function used 365 in SQL execution graphs. 366 @return query thread to run next or NULL */ 367 UNIV_INTERN 368 que_thr_t* 369 row_upd_step( 370 /*=========*/ 371 que_thr_t* thr); /*!< in: query thread */ 372 #endif /* !UNIV_HOTBACKUP */ 373 /*********************************************************************//** 374 Parses the log data of system field values. 375 @return log data end or NULL */ 376 UNIV_INTERN 377 byte* 378 row_upd_parse_sys_vals( 379 /*===================*/ 380 byte* ptr, /*!< in: buffer */ 381 byte* end_ptr,/*!< in: buffer end */ 382 ulint* pos, /*!< out: TRX_ID position in record */ 383 trx_id_t* trx_id, /*!< out: trx id */ 384 roll_ptr_t* roll_ptr);/*!< out: roll ptr */ 385 /*********************************************************************//** 386 Updates the trx id and roll ptr field in a clustered index record in database 387 recovery. */ 388 UNIV_INTERN 389 void 390 row_upd_rec_sys_fields_in_recovery( 391 /*===============================*/ 392 rec_t* rec, /*!< in/out: record */ 393 page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */ 394 const ulint* offsets,/*!< in: array returned by rec_get_offsets() */ 395 ulint pos, /*!< in: TRX_ID position in rec */ 396 trx_id_t trx_id, /*!< in: transaction id */ 397 roll_ptr_t roll_ptr);/*!< in: roll ptr of the undo log record */ 398 /*********************************************************************//** 399 Parses the log data written by row_upd_index_write_log. 400 @return log data end or NULL */ 401 UNIV_INTERN 402 byte* 403 row_upd_index_parse( 404 /*================*/ 405 byte* ptr, /*!< in: buffer */ 406 byte* end_ptr,/*!< in: buffer end */ 407 mem_heap_t* heap, /*!< in: memory heap where update vector is 408 built */ 409 upd_t** update_out);/*!< out: update vector */ 410 411 412 /* Update vector field */ 413 struct upd_field_t{ 414 unsigned field_no:16; /*!< field number in an index, usually 415 the clustered index, but in updating 416 a secondary index record in btr0cur.cc 417 this is the position in the secondary 418 index */ 419 #ifndef UNIV_HOTBACKUP 420 unsigned orig_len:16; /*!< original length of the locally 421 stored part of an externally stored 422 column, or 0 */ 423 que_node_t* exp; /*!< expression for calculating a new 424 value: it refers to column values and 425 constants in the symbol table of the 426 query graph */ 427 #endif /* !UNIV_HOTBACKUP */ 428 dfield_t new_val; /*!< new value for the column */ 429 }; 430 431 /* Update vector structure */ 432 struct upd_t{ 433 ulint info_bits; /*!< new value of info bits to record; 434 default is 0 */ 435 ulint n_fields; /*!< number of update fields */ 436 upd_field_t* fields; /*!< array of update fields */ 437 }; 438 439 #ifndef UNIV_HOTBACKUP 440 /* Update node structure which also implements the delete operation 441 of a row */ 442 443 struct upd_node_t{ 444 que_common_t common; /*!< node type: QUE_NODE_UPDATE */ 445 ibool is_delete;/* TRUE if delete, FALSE if update */ 446 ibool searched_update; 447 /* TRUE if searched update, FALSE if 448 positioned */ 449 ibool in_mysql_interface; 450 /* TRUE if the update node was created 451 for the MySQL interface */ 452 dict_foreign_t* foreign;/* NULL or pointer to a foreign key 453 constraint if this update node is used in 454 doing an ON DELETE or ON UPDATE operation */ 455 upd_node_t* cascade_node;/* NULL or an update node template which 456 is used to implement ON DELETE/UPDATE CASCADE 457 or ... SET NULL for foreign keys */ 458 mem_heap_t* cascade_heap;/* NULL or a mem heap where the cascade 459 node is created */ 460 sel_node_t* select; /*!< query graph subtree implementing a base 461 table cursor: the rows returned will be 462 updated */ 463 btr_pcur_t* pcur; /*!< persistent cursor placed on the clustered 464 index record which should be updated or 465 deleted; the cursor is stored in the graph 466 of 'select' field above, except in the case 467 of the MySQL interface */ 468 dict_table_t* table; /*!< table where updated */ 469 upd_t* update; /*!< update vector for the row */ 470 ulint update_n_fields; 471 /* when this struct is used to implement 472 a cascade operation for foreign keys, we store 473 here the size of the buffer allocated for use 474 as the update vector */ 475 sym_node_list_t columns;/* symbol table nodes for the columns 476 to retrieve from the table */ 477 ibool has_clust_rec_x_lock; 478 /* TRUE if the select which retrieves the 479 records to update already sets an x-lock on 480 the clustered record; note that it must always 481 set at least an s-lock */ 482 ulint cmpl_info;/* information extracted during query 483 compilation; speeds up execution: 484 UPD_NODE_NO_ORD_CHANGE and 485 UPD_NODE_NO_SIZE_CHANGE, ORed */ 486 /*----------------------*/ 487 /* Local storage for this graph node */ 488 ulint state; /*!< node execution state */ 489 dict_index_t* index; /*!< NULL, or the next index whose record should 490 be updated */ 491 dtuple_t* row; /*!< NULL, or a copy (also fields copied to 492 heap) of the row to update; this must be reset 493 to NULL after a successful update */ 494 row_ext_t* ext; /*!< NULL, or prefixes of the externally 495 stored columns in the old row */ 496 dtuple_t* upd_row;/* NULL, or a copy of the updated row */ 497 row_ext_t* upd_ext;/* NULL, or prefixes of the externally 498 stored columns in upd_row */ 499 mem_heap_t* heap; /*!< memory heap used as auxiliary storage; 500 this must be emptied after a successful 501 update */ 502 /*----------------------*/ 503 sym_node_t* table_sym;/* table node in symbol table */ 504 que_node_t* col_assign_list; 505 /* column assignment list */ 506 ulint magic_n; 507 }; 508 509 #define UPD_NODE_MAGIC_N 1579975 510 511 /* Node execution states */ 512 #define UPD_NODE_SET_IX_LOCK 1 /* execution came to the node from 513 a node above and if the field 514 has_clust_rec_x_lock is FALSE, we 515 should set an intention x-lock on 516 the table */ 517 #define UPD_NODE_UPDATE_CLUSTERED 2 /* clustered index record should be 518 updated */ 519 #define UPD_NODE_INSERT_CLUSTERED 3 /* clustered index record should be 520 inserted, old record is already delete 521 marked */ 522 #define UPD_NODE_INSERT_BLOB 4 /* clustered index record should be 523 inserted, old record is already 524 delete-marked; non-updated BLOBs 525 should be inherited by the new record 526 and disowned by the old record */ 527 #define UPD_NODE_UPDATE_ALL_SEC 5 /* an ordering field of the clustered 528 index record was changed, or this is 529 a delete operation: should update 530 all the secondary index records */ 531 #define UPD_NODE_UPDATE_SOME_SEC 6 /* secondary index entries should be 532 looked at and updated if an ordering 533 field changed */ 534 535 /* Compilation info flags: these must fit within 3 bits; see trx0rec.h */ 536 #define UPD_NODE_NO_ORD_CHANGE 1 /* no secondary index record will be 537 changed in the update and no ordering 538 field of the clustered index */ 539 #define UPD_NODE_NO_SIZE_CHANGE 2 /* no record field size will be 540 changed in the update */ 541 542 #endif /* !UNIV_HOTBACKUP */ 543 544 #ifndef UNIV_NONINL 545 #include "row0upd.ic" 546 #endif 547 548 #endif 549