1 /***************************************************************************** 2 3 Copyright (c) 1996, 2018, Oracle and/or its affiliates. All Rights Reserved. 4 Copyright (c) 2017, 2020, MariaDB Corporation. 5 6 This program is free software; you can redistribute it and/or modify it under 7 the terms of the GNU General Public License as published by the Free Software 8 Foundation; version 2 of the License. 9 10 This program is distributed in the hope that it will be useful, but WITHOUT 11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License along with 15 this program; if not, write to the Free Software Foundation, Inc., 16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA 17 18 *****************************************************************************/ 19 20 /**************************************************//** 21 @file include/row0upd.h 22 Update of a row 23 24 Created 12/27/1996 Heikki Tuuri 25 *******************************************************/ 26 27 #ifndef row0upd_h 28 #define row0upd_h 29 30 #include "data0data.h" 31 #include "rem0types.h" 32 #include "row0types.h" 33 #include "btr0types.h" 34 #include "trx0types.h" 35 #include "btr0pcur.h" 36 #include "que0types.h" 37 #include "pars0types.h" 38 39 /*********************************************************************//** 40 Creates an update vector object. 41 @return own: update vector object */ 42 UNIV_INLINE 43 upd_t* 44 upd_create( 45 /*=======*/ 46 ulint n, /*!< in: number of fields */ 47 mem_heap_t* heap); /*!< in: heap from which memory allocated */ 48 /*********************************************************************//** 49 Returns the number of fields in the update vector == number of columns 50 to be updated by an update vector. 51 @return number of fields */ 52 UNIV_INLINE 53 ulint 54 upd_get_n_fields( 55 /*=============*/ 56 const upd_t* update); /*!< in: update vector */ 57 #ifdef UNIV_DEBUG 58 /*********************************************************************//** 59 Returns the nth field of an update vector. 60 @return update vector field */ 61 UNIV_INLINE 62 upd_field_t* 63 upd_get_nth_field( 64 /*==============*/ 65 const upd_t* update, /*!< in: update vector */ 66 ulint n); /*!< in: field position in update vector */ 67 #else 68 # define upd_get_nth_field(update, n) ((update)->fields + (n)) 69 #endif 70 71 /*********************************************************************//** 72 Sets an index field number to be updated by an update vector field. */ 73 UNIV_INLINE 74 void 75 upd_field_set_field_no( 76 /*===================*/ 77 upd_field_t* upd_field, /*!< in: update vector field */ 78 ulint field_no, /*!< in: field number in a clustered 79 index */ 80 dict_index_t* index); 81 82 /** set field number to a update vector field, marks this field is updated 83 @param[in,out] upd_field update vector field 84 @param[in] field_no virtual column sequence num 85 @param[in] index index */ 86 UNIV_INLINE 87 void 88 upd_field_set_v_field_no( 89 upd_field_t* upd_field, 90 ulint field_no, 91 dict_index_t* index); 92 /*********************************************************************//** 93 Returns a field of an update vector by field_no. 94 @return update vector field, or NULL */ 95 UNIV_INLINE 96 const upd_field_t* 97 upd_get_field_by_field_no( 98 /*======================*/ 99 const upd_t* update, /*!< in: update vector */ 100 ulint no, /*!< in: field_no */ 101 bool is_virtual) /*!< in: if it is a virtual column */ 102 MY_ATTRIBUTE((warn_unused_result)); 103 /*********************************************************************//** 104 Updates the trx id and roll ptr field in a clustered index record when 105 a row is updated or marked deleted. */ 106 UNIV_INLINE 107 void 108 row_upd_rec_sys_fields( 109 /*===================*/ 110 rec_t* rec, /*!< in/out: record */ 111 page_zip_des_t* page_zip,/*!< in/out: compressed page whose 112 uncompressed part will be updated, or NULL */ 113 dict_index_t* index, /*!< in: clustered index */ 114 const rec_offs* offsets,/*!< in: rec_get_offsets(rec, index) */ 115 const trx_t* trx, /*!< in: transaction */ 116 roll_ptr_t roll_ptr);/*!< in: DB_ROLL_PTR to the undo log */ 117 /*********************************************************************//** 118 Creates an update node for a query graph. 119 @return own: update node */ 120 upd_node_t* 121 upd_node_create( 122 /*============*/ 123 mem_heap_t* heap); /*!< in: mem heap where created */ 124 /***********************************************************//** 125 Writes to the redo log the new values of the fields occurring in the index. */ 126 void 127 row_upd_index_write_log( 128 /*====================*/ 129 const upd_t* update, /*!< in: update vector */ 130 byte* log_ptr,/*!< in: pointer to mlog buffer: must 131 contain at least MLOG_BUF_MARGIN bytes 132 of free space; the buffer is closed 133 within this function */ 134 mtr_t* mtr); /*!< in: mtr into whose log to write */ 135 /***********************************************************//** 136 Returns TRUE if row update changes size of some field in index or if some 137 field to be updated is stored externally in rec or update. 138 @return TRUE if the update changes the size of some field in index or 139 the field is external in rec or update */ 140 ibool 141 row_upd_changes_field_size_or_external( 142 /*===================================*/ 143 dict_index_t* index, /*!< in: index */ 144 const rec_offs* offsets,/*!< in: rec_get_offsets(rec, index) */ 145 const upd_t* update);/*!< in: update vector */ 146 /***********************************************************//** 147 Returns true if row update contains disowned external fields. 148 @return true if the update contains disowned external fields. */ 149 bool 150 row_upd_changes_disowned_external( 151 /*==============================*/ 152 const upd_t* update) /*!< in: update vector */ 153 MY_ATTRIBUTE((nonnull, warn_unused_result)); 154 /***********************************************************//** 155 Replaces the new column values stored in the update vector to the 156 record given. No field size changes are allowed. This function is 157 usually invoked on a clustered index. The only use case for a 158 secondary index is row_ins_sec_index_entry_by_modify() or its 159 counterpart in ibuf_insert_to_index_page(). */ 160 void 161 row_upd_rec_in_place( 162 /*=================*/ 163 rec_t* rec, /*!< in/out: record where replaced */ 164 dict_index_t* index, /*!< in: the index the record belongs to */ 165 const rec_offs* offsets,/*!< in: array returned by rec_get_offsets() */ 166 const upd_t* update, /*!< in: update vector */ 167 page_zip_des_t* page_zip);/*!< in: compressed page with enough space 168 available, or NULL */ 169 170 /***************************************************************//** 171 Builds an update vector from those fields which in a secondary index entry 172 differ from a record that has the equal ordering fields. NOTE: we compare 173 the fields as binary strings! 174 @return own: update vector of differing fields */ 175 upd_t* 176 row_upd_build_sec_rec_difference_binary( 177 /*====================================*/ 178 const rec_t* rec, /*!< in: secondary index record */ 179 dict_index_t* index, /*!< in: index */ 180 const rec_offs* offsets,/*!< in: rec_get_offsets(rec, index) */ 181 const dtuple_t* entry, /*!< in: entry to insert */ 182 mem_heap_t* heap) /*!< in: memory heap from which allocated */ 183 MY_ATTRIBUTE((warn_unused_result, nonnull)); 184 /** Builds an update vector from those fields, excluding the roll ptr and 185 trx id fields, which in an index entry differ from a record that has 186 the equal ordering fields. NOTE: we compare the fields as binary strings! 187 @param[in] index clustered index 188 @param[in] entry clustered index entry to insert 189 @param[in] rec clustered index record 190 @param[in] offsets rec_get_offsets(rec,index), or NULL 191 @param[in] no_sys skip the system columns 192 DB_TRX_ID and DB_ROLL_PTR 193 @param[in] trx transaction (for diagnostics), 194 or NULL 195 @param[in] heap memory heap from which allocated 196 @param[in,out] mysql_table NULL, or mysql table object when 197 user thread invokes dml 198 @param[out] error error number in case of failure 199 @return own: update vector of differing fields, excluding roll ptr and 200 trx id */ 201 upd_t* 202 row_upd_build_difference_binary( 203 dict_index_t* index, 204 const dtuple_t* entry, 205 const rec_t* rec, 206 const rec_offs* offsets, 207 bool no_sys, 208 trx_t* trx, 209 mem_heap_t* heap, 210 TABLE* mysql_table, 211 dberr_t* error) 212 MY_ATTRIBUTE((nonnull(1,2,3,7,9), warn_unused_result)); 213 /** Apply an update vector to an index entry. 214 @param[in,out] entry index entry to be updated; the clustered index record 215 must be covered by a lock or a page latch to prevent 216 deletion (rollback or purge) 217 @param[in] index index of the entry 218 @param[in] update update vector built for the entry 219 @param[in,out] heap memory heap for copying off-page columns */ 220 void 221 row_upd_index_replace_new_col_vals_index_pos( 222 dtuple_t* entry, 223 const dict_index_t* index, 224 const upd_t* update, 225 mem_heap_t* heap) 226 MY_ATTRIBUTE((nonnull)); 227 /** Replace the new column values stored in the update vector, 228 during trx_undo_prev_version_build(). 229 @param entry clustered index tuple where the values are replaced 230 (the clustered index leaf page latch must be held) 231 @param index clustered index 232 @param update update vector for the clustered index 233 @param heap memory heap for allocating and copying values 234 @return whether the previous version was built successfully */ 235 bool 236 row_upd_index_replace_new_col_vals(dtuple_t *entry, const dict_index_t &index, 237 const upd_t *update, mem_heap_t *heap) 238 MY_ATTRIBUTE((nonnull, warn_unused_result)); 239 /***********************************************************//** 240 Replaces the new column values stored in the update vector. */ 241 void 242 row_upd_replace( 243 /*============*/ 244 dtuple_t* row, /*!< in/out: row where replaced, 245 indexed by col_no; 246 the clustered index record must be 247 covered by a lock or a page latch to 248 prevent deletion (rollback or purge) */ 249 row_ext_t** ext, /*!< out, own: NULL, or externally 250 stored column prefixes */ 251 const dict_index_t* index, /*!< in: clustered index */ 252 const upd_t* update, /*!< in: an update vector built for the 253 clustered index */ 254 mem_heap_t* heap); /*!< in: memory heap */ 255 /** Replaces the virtual column values stored in a dtuple with that of 256 a update vector. 257 @param[in,out] row dtuple whose column to be updated 258 @param[in] table table 259 @param[in] update an update vector built for the clustered index 260 @param[in] upd_new update to new or old value 261 @param[in,out] undo_row undo row (if needs to be updated) 262 @param[in] ptr remaining part in update undo log */ 263 void 264 row_upd_replace_vcol( 265 dtuple_t* row, 266 const dict_table_t* table, 267 const upd_t* update, 268 bool upd_new, 269 dtuple_t* undo_row, 270 const byte* ptr); 271 272 /***********************************************************//** 273 Checks if an update vector changes an ordering field of an index record. 274 275 This function is fast if the update vector is short or the number of ordering 276 fields in the index is small. Otherwise, this can be quadratic. 277 NOTE: we compare the fields as binary strings! 278 @return TRUE if update vector changes an ordering field in the index record */ 279 ibool 280 row_upd_changes_ord_field_binary_func( 281 /*==================================*/ 282 dict_index_t* index, /*!< in: index of the record */ 283 const upd_t* update, /*!< in: update vector for the row; NOTE: the 284 field numbers in this MUST be clustered index 285 positions! */ 286 #ifdef UNIV_DEBUG 287 const que_thr_t*thr, /*!< in: query thread */ 288 #endif /* UNIV_DEBUG */ 289 const dtuple_t* row, /*!< in: old value of row, or NULL if the 290 row and the data values in update are not 291 known when this function is called, e.g., at 292 compile time */ 293 const row_ext_t*ext, /*!< NULL, or prefixes of the externally 294 stored columns in the old row */ 295 ulint flag) /*!< in: ROW_BUILD_NORMAL, 296 ROW_BUILD_FOR_PURGE or ROW_BUILD_FOR_UNDO */ 297 MY_ATTRIBUTE((nonnull(1,2), warn_unused_result)); 298 #ifdef UNIV_DEBUG 299 # define row_upd_changes_ord_field_binary(index,update,thr,row,ext) \ 300 row_upd_changes_ord_field_binary_func(index,update,thr,row,ext,0) 301 #else /* UNIV_DEBUG */ 302 # define row_upd_changes_ord_field_binary(index,update,thr,row,ext) \ 303 row_upd_changes_ord_field_binary_func(index,update,row,ext,0) 304 #endif /* UNIV_DEBUG */ 305 /***********************************************************//** 306 Checks if an FTS indexed column is affected by an UPDATE. 307 @return offset within fts_t::indexes if FTS indexed column updated else 308 ULINT_UNDEFINED */ 309 ulint 310 row_upd_changes_fts_column( 311 /*=======================*/ 312 dict_table_t* table, /*!< in: table */ 313 upd_field_t* upd_field); /*!< in: field to check */ 314 /***********************************************************//** 315 Checks if an FTS Doc ID column is affected by an UPDATE. 316 @return whether Doc ID column is affected */ 317 bool 318 row_upd_changes_doc_id( 319 /*===================*/ 320 dict_table_t* table, /*!< in: table */ 321 upd_field_t* upd_field) /*!< in: field to check */ 322 MY_ATTRIBUTE((nonnull, warn_unused_result)); 323 /***********************************************************//** 324 Checks if an update vector changes an ordering field of an index record. 325 This function is fast if the update vector is short or the number of ordering 326 fields in the index is small. Otherwise, this can be quadratic. 327 NOTE: we compare the fields as binary strings! 328 @return TRUE if update vector may change an ordering field in an index 329 record */ 330 ibool 331 row_upd_changes_some_index_ord_field_binary( 332 /*========================================*/ 333 const dict_table_t* table, /*!< in: table */ 334 const upd_t* update);/*!< in: update vector for the row */ 335 /***********************************************************//** 336 Updates a row in a table. This is a high-level function used 337 in SQL execution graphs. 338 @return query thread to run next or NULL */ 339 que_thr_t* 340 row_upd_step( 341 /*=========*/ 342 que_thr_t* thr); /*!< in: query thread */ 343 /*********************************************************************//** 344 Parses the log data of system field values. 345 @return log data end or NULL */ 346 byte* 347 row_upd_parse_sys_vals( 348 /*===================*/ 349 const byte* ptr, /*!< in: buffer */ 350 const byte* end_ptr,/*!< in: buffer end */ 351 ulint* pos, /*!< out: TRX_ID position in record */ 352 trx_id_t* trx_id, /*!< out: trx id */ 353 roll_ptr_t* roll_ptr);/*!< out: roll ptr */ 354 /*********************************************************************//** 355 Updates the trx id and roll ptr field in a clustered index record in database 356 recovery. */ 357 void 358 row_upd_rec_sys_fields_in_recovery( 359 /*===============================*/ 360 rec_t* rec, /*!< in/out: record */ 361 page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */ 362 const rec_offs* offsets,/*!< in: array returned by rec_get_offsets() */ 363 ulint pos, /*!< in: TRX_ID position in rec */ 364 trx_id_t trx_id, /*!< in: transaction id */ 365 roll_ptr_t roll_ptr);/*!< in: roll ptr of the undo log record */ 366 /*********************************************************************//** 367 Parses the log data written by row_upd_index_write_log. 368 @return log data end or NULL */ 369 byte* 370 row_upd_index_parse( 371 /*================*/ 372 const byte* ptr, /*!< in: buffer */ 373 const byte* end_ptr,/*!< in: buffer end */ 374 mem_heap_t* heap, /*!< in: memory heap where update vector is 375 built */ 376 upd_t** update_out);/*!< out: update vector */ 377 378 379 /* Update vector field */ 380 struct upd_field_t{ 381 unsigned field_no:16; /*!< field number in an index, usually 382 the clustered index, but in updating 383 a secondary index record in btr0cur.cc 384 this is the position in the secondary 385 index. If this field is a virtual 386 column, then field_no represents 387 the nth virtual column in the table */ 388 unsigned orig_len:16; /*!< original length of the locally 389 stored part of an externally stored 390 column, or 0 */ 391 que_node_t* exp; /*!< expression for calculating a new 392 value: it refers to column values and 393 constants in the symbol table of the 394 query graph */ 395 dfield_t new_val; /*!< new value for the column */ 396 dfield_t* old_v_val; /*!< old value for the virtual column */ 397 }; 398 399 400 /* check whether an update field is on virtual column */ 401 #define upd_fld_is_virtual_col(upd_fld) \ 402 (((upd_fld)->new_val.type.prtype & DATA_VIRTUAL) == DATA_VIRTUAL) 403 404 /* set DATA_VIRTUAL bit on update field to show it is a virtual column */ 405 #define upd_fld_set_virtual_col(upd_fld) \ 406 ((upd_fld)->new_val.type.prtype |= DATA_VIRTUAL) 407 408 /* Update vector structure */ 409 struct upd_t{ 410 mem_heap_t* heap; /*!< heap from which memory allocated */ 411 ulint info_bits; /*!< new value of info bits to record; 412 default is 0 */ 413 dtuple_t* old_vrow; /*!< pointer to old row, used for 414 virtual column update now */ 415 ulint n_fields; /*!< number of update fields */ 416 upd_field_t* fields; /*!< array of update fields */ 417 byte vers_sys_value[8]; /*!< buffer for updating system fields */ 418 419 /** Append an update field to the end of array 420 @param[in] field an update field */ appendupd_t421 void append(const upd_field_t& field) 422 { 423 fields[n_fields++] = field; 424 } 425 remove_elementupd_t426 void remove_element(ulint i) 427 { 428 ut_ad(n_fields > 0); 429 ut_ad(i < n_fields); 430 while (i < n_fields - 1) 431 { 432 fields[i]= fields[i + 1]; 433 i++; 434 } 435 n_fields--; 436 } 437 removeupd_t438 bool remove(const ulint field_no) 439 { 440 for (ulint i= 0; i < n_fields; ++i) 441 { 442 if (field_no == fields[i].field_no) 443 { 444 remove_element(i); 445 return true; 446 } 447 } 448 return false; 449 } 450 451 /** Determine if the given field_no is modified. 452 @return true if modified, false otherwise. */ is_modifiedupd_t453 bool is_modified(const ulint field_no) const 454 { 455 for (ulint i = 0; i < n_fields; ++i) { 456 if (field_no == fields[i].field_no) { 457 return(true); 458 } 459 } 460 return(false); 461 } 462 463 /** Determine if the update affects a system versioned column or row_end. */ affects_versionedupd_t464 bool affects_versioned() const 465 { 466 for (ulint i = 0; i < n_fields; i++) { 467 dtype_t type = fields[i].new_val.type; 468 if (type.is_versioned()) { 469 return true; 470 } 471 // versioned DELETE is UPDATE SET row_end=NOW 472 if (type.vers_sys_end()) { 473 return true; 474 } 475 } 476 return false; 477 } 478 479 /** @return whether this is for a hidden metadata record 480 for instant ALTER TABLE */ is_metadataupd_t481 bool is_metadata() const { return dtuple_t::is_metadata(info_bits); } 482 /** @return whether this is for a hidden metadata record 483 for instant ALTER TABLE (not only ADD COLUMN) */ is_alter_metadataupd_t484 bool is_alter_metadata() const 485 { return dtuple_t::is_alter_metadata(info_bits); } 486 487 #ifdef UNIV_DEBUG validateupd_t488 bool validate() const 489 { 490 for (ulint i = 0; i < n_fields; ++i) { 491 dfield_t* field = &fields[i].new_val; 492 if (dfield_is_ext(field)) { 493 ut_ad(dfield_get_len(field) 494 >= BTR_EXTERN_FIELD_REF_SIZE); 495 } 496 } 497 return(true); 498 } 499 #endif // UNIV_DEBUG 500 }; 501 502 /** Kinds of update operation */ 503 enum delete_mode_t { 504 NO_DELETE = 0, /*!< this operation does not delete */ 505 PLAIN_DELETE, /*!< ordinary delete */ 506 VERSIONED_DELETE /*!< update old and insert a new row */ 507 }; 508 509 /* Update node structure which also implements the delete operation 510 of a row */ 511 512 struct upd_node_t{ 513 que_common_t common; /*!< node type: QUE_NODE_UPDATE */ 514 delete_mode_t is_delete; /*!< kind of DELETE */ 515 ibool searched_update; 516 /* TRUE if searched update, FALSE if 517 positioned */ 518 bool in_mysql_interface; 519 /* whether the update node was created 520 for the MySQL interface */ 521 dict_foreign_t* foreign;/* NULL or pointer to a foreign key 522 constraint if this update node is used in 523 doing an ON DELETE or ON UPDATE operation */ 524 upd_node_t* cascade_node;/* NULL or an update node template which 525 is used to implement ON DELETE/UPDATE CASCADE 526 or ... SET NULL for foreign keys */ 527 mem_heap_t* cascade_heap; 528 /*!< NULL or a mem heap where cascade 529 node is created.*/ 530 sel_node_t* select; /*!< query graph subtree implementing a base 531 table cursor: the rows returned will be 532 updated */ 533 btr_pcur_t* pcur; /*!< persistent cursor placed on the clustered 534 index record which should be updated or 535 deleted; the cursor is stored in the graph 536 of 'select' field above, except in the case 537 of the MySQL interface */ 538 dict_table_t* table; /*!< table where updated */ 539 upd_t* update; /*!< update vector for the row */ 540 ulint update_n_fields; 541 /* when this struct is used to implement 542 a cascade operation for foreign keys, we store 543 here the size of the buffer allocated for use 544 as the update vector */ 545 sym_node_list_t columns;/* symbol table nodes for the columns 546 to retrieve from the table */ 547 ibool has_clust_rec_x_lock; 548 /* TRUE if the select which retrieves the 549 records to update already sets an x-lock on 550 the clustered record; note that it must always 551 set at least an s-lock */ 552 ulint cmpl_info;/* information extracted during query 553 compilation; speeds up execution: 554 UPD_NODE_NO_ORD_CHANGE and 555 UPD_NODE_NO_SIZE_CHANGE, ORed */ 556 /*----------------------*/ 557 /* Local storage for this graph node */ 558 ulint state; /*!< node execution state */ 559 dict_index_t* index; /*!< NULL, or the next index whose record should 560 be updated */ 561 dtuple_t* row; /*!< NULL, or a copy (also fields copied to 562 heap) of the row to update; this must be reset 563 to NULL after a successful update */ 564 dtuple_t* historical_row; /*!< historical row used in 565 CASCADE UPDATE/SET NULL; 566 allocated from historical_heap */ 567 mem_heap_t* historical_heap; /*!< heap for historical row insertion; 568 created when row to update is located; 569 freed right before row update */ 570 row_ext_t* ext; /*!< NULL, or prefixes of the externally 571 stored columns in the old row */ 572 dtuple_t* upd_row;/* NULL, or a copy of the updated row */ 573 row_ext_t* upd_ext;/* NULL, or prefixes of the externally 574 stored columns in upd_row */ 575 mem_heap_t* heap; /*!< memory heap used as auxiliary storage; 576 this must be emptied after a successful 577 update */ 578 /*----------------------*/ 579 sym_node_t* table_sym;/* table node in symbol table */ 580 que_node_t* col_assign_list; 581 /* column assignment list */ 582 ulint magic_n; 583 584 private: 585 /** Appends row_start or row_end field to update vector and sets a 586 CURRENT_TIMESTAMP/trx->id value to it. 587 Supposed to be called only by make_versioned_update() and 588 make_versioned_delete(). 589 @param[in] trx transaction 590 @param[in] vers_sys_idx table->row_start or table->row_end */ 591 void vers_update_fields(const trx_t *trx, ulint idx); 592 593 public: 594 /** Also set row_start = CURRENT_TIMESTAMP/trx->id 595 @param[in] trx transaction */ vers_make_updateupd_node_t596 void vers_make_update(const trx_t *trx) 597 { 598 vers_update_fields(trx, table->vers_start); 599 } 600 601 /** Only set row_end = CURRENT_TIMESTAMP/trx->id. 602 Do not touch other fields at all. 603 @param[in] trx transaction */ vers_make_deleteupd_node_t604 void vers_make_delete(const trx_t *trx) 605 { 606 update->n_fields = 0; 607 is_delete = VERSIONED_DELETE; 608 vers_update_fields(trx, table->vers_end); 609 } 610 }; 611 612 #define UPD_NODE_MAGIC_N 1579975 613 614 /* Node execution states */ 615 #define UPD_NODE_SET_IX_LOCK 1 /* execution came to the node from 616 a node above and if the field 617 has_clust_rec_x_lock is FALSE, we 618 should set an intention x-lock on 619 the table */ 620 #define UPD_NODE_UPDATE_CLUSTERED 2 /* clustered index record should be 621 updated */ 622 #define UPD_NODE_INSERT_CLUSTERED 3 /* clustered index record should be 623 inserted, old record is already delete 624 marked */ 625 #define UPD_NODE_UPDATE_ALL_SEC 5 /* an ordering field of the clustered 626 index record was changed, or this is 627 a delete operation: should update 628 all the secondary index records */ 629 #define UPD_NODE_UPDATE_SOME_SEC 6 /* secondary index entries should be 630 looked at and updated if an ordering 631 field changed */ 632 633 /* Compilation info flags: these must fit within 3 bits; see trx0rec.h */ 634 #define UPD_NODE_NO_ORD_CHANGE 1 /* no secondary index record will be 635 changed in the update and no ordering 636 field of the clustered index */ 637 #define UPD_NODE_NO_SIZE_CHANGE 2 /* no record field size will be 638 changed in the update */ 639 640 641 #include "row0upd.inl" 642 643 #endif 644