MySQL 8.1.0
Source Code Documentation
row0upd.h
Go to the documentation of this file.
1/*****************************************************************************
2
3Copyright (c) 1996, 2023, Oracle and/or its affiliates.
4
5This program is free software; you can redistribute it and/or modify it under
6the terms of the GNU General Public License, version 2.0, as published by the
7Free Software Foundation.
8
9This program is also distributed with certain software (including but not
10limited to OpenSSL) that is licensed under separate terms, as designated in a
11particular file or component or in included license documentation. The authors
12of MySQL hereby grant you an additional permission to link the program and
13your derivative works with the separately licensed software that they have
14included with MySQL.
15
16This program is distributed in the hope that it will be useful, but WITHOUT
17ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
19for more details.
20
21You should have received a copy of the GNU General Public License along with
22this program; if not, write to the Free Software Foundation, Inc.,
2351 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24
25*****************************************************************************/
26
27/** @file include/row0upd.h
28 Update of a row
29
30 Created 12/27/1996 Heikki Tuuri
31 *******************************************************/
32
33#ifndef row0upd_h
34#define row0upd_h
35
36#include <stack>
37#include "btr0types.h"
38#include "data0data.h"
39#include "dict0types.h"
40#include "lob0lob.h"
41#include "row0types.h"
42#include "table.h"
43#include "trx0types.h"
44#include "univ.i"
45
46#include "btr0pcur.h"
47#ifndef UNIV_HOTBACKUP
48#include "pars0types.h"
49#include "que0types.h"
50#endif /* !UNIV_HOTBACKUP */
51
52/** Creates an update vector object.
53@param[in] n number of fields
54@param[in] heap heap from which memory allocated
55@return own: update vector object */
56static inline upd_t *upd_create(ulint n, mem_heap_t *heap);
57
58/** Returns the number of fields in the update vector == number of columns
59 to be updated by an update vector.
60 @return number of fields */
61static inline ulint upd_get_n_fields(
62 const upd_t *update); /*!< in: update vector */
63
64#ifdef UNIV_DEBUG
65/** Returns the nth field of an update vector.
66@param[in] update update vector
67@param[in] n field position in update vector
68@return update vector field */
70#else
71#define upd_get_nth_field(update, n) ((update)->fields + (n))
72#endif
73/** Sets an index field number to be updated by an update vector field.
74@param[in] upd_field update vector field
75@param[in] field_no field number in a clustered index
76@param[in] index index */
77static inline void upd_field_set_field_no(upd_field_t *upd_field,
78 ulint field_no,
79 const dict_index_t *index);
80
81/** set field number to a update vector field, marks this field is updated
82@param[in,out] upd_field update vector field
83@param[in] field_no virtual column sequence num
84@param[in] index index */
85static inline void upd_field_set_v_field_no(upd_field_t *upd_field,
86 ulint field_no,
87 const dict_index_t *index);
88/** Returns a field of an update vector by field_no.
89@param[in] update Update vector.
90@param[in] no Field no.
91@param[in] is_virtual If it is a virtual column.
92@return update vector field, or nullptr. */
93[[nodiscard]] static inline const upd_field_t *upd_get_field_by_field_no(
94 const upd_t *update, ulint no, bool is_virtual);
95/** Writes into the redo log the values of trx id and roll ptr and enough info
96to determine their positions within a clustered index record.
97@param[in] index Clustered index.
98@param[in] trx_id Transaction ID.
99@param[in] roll_ptr Roll ptr of the undo log record.
100@param[in] log_ptr Pointer to a buffer of size > 20 opened in mlog.
101@param[in] mtr Mini-transaction.
102@return new pointer to mlog */
104 roll_ptr_t roll_ptr, byte *log_ptr,
105 mtr_t *mtr);
106
107#ifndef UNIV_HOTBACKUP
108/** Updates the trx id and roll ptr field in a clustered index record when a
109row is updated or marked deleted.
110@param[in,out] rec record
111@param[in,out] page_zip compressed page whose uncompressed part will
112 be updated, or NULL
113@param[in] index clustered index
114@param[in] offsets rec_get_offsets(rec, index)
115@param[in] trx transaction
116@param[in] roll_ptr roll ptr of the undo log record, can be 0
117 during IMPORT */
118static inline void row_upd_rec_sys_fields(rec_t *rec, page_zip_des_t *page_zip,
119 const dict_index_t *index,
120 const ulint *offsets,
121 const trx_t *trx,
122 roll_ptr_t roll_ptr);
123#endif /* !UNIV_HOTBACKUP */
124
125/** Sets the trx id or roll ptr field of a clustered index entry.
126@param[in,out] entry Index entry, where the memory buffers for sys fields are
127already allocated: the function just copies the new values to them
128@param[in] index Clustered index
129@param[in] type Data_trx_id or data_roll_ptr
130@param[in] val Value to write */
132 ulint type, uint64_t val);
133
134/** Creates an update node for a query graph.
135 @return own: update node */
137 mem_heap_t *heap); /*!< in: mem heap where created */
138
139/** Writes to the redo log the new values of the fields occurring in the index.
140@param[in] index index which to be updated
141@param[in] update update vector
142@param[in] log_ptr pointer to mlog buffer: must contain at least
143 MLOG_BUF_MARGIN bytes of free space; the buffer
144 is closed within this function
145@param[in] mtr mtr into whose log to write */
147 byte *log_ptr, mtr_t *mtr);
148
149/** Returns true if row update changes size of some field in index or if some
150 field to be updated is stored externally in rec or update.
151 @return true if the update changes the size of some field in index or
152 the field is external in rec or update */
154 const dict_index_t *index, /*!< in: index */
155 const ulint *offsets, /*!< in: rec_get_offsets(rec, index) */
156 const upd_t *update); /*!< in: update vector */
157/** Returns true if row update contains disowned external fields.
158 @return true if the update contains disowned external fields. */
159[[nodiscard]] bool row_upd_changes_disowned_external(
160 const upd_t *update); /*!< in: update vector */
161/** Replaces the new column values stored in the update vector to the
162 record given. No field size changes are allowed. This function is
163 usually invoked on a clustered index. The only use case for a
164 secondary index is row_ins_sec_index_entry_by_modify() or its
165 counterpart in ibuf_insert_to_index_page(). */
167 rec_t *rec, /*!< in/out: record where replaced */
168 const dict_index_t *index, /*!< in: the index the record belongs to */
169 const ulint *offsets, /*!< in: array returned by rec_get_offsets() */
170 const upd_t *update, /*!< in: update vector */
171 page_zip_des_t *page_zip); /*!< in: compressed page with enough space
172 available, or NULL */
173/** Builds an update vector from those fields which in a secondary index entry
174 differ from a record that has the equal ordering fields. NOTE: we compare
175 the fields as binary strings!
176 @return own: update vector of differing fields */
178 const rec_t *rec, /*!< in: secondary index record */
179 dict_index_t *index, /*!< in: index */
180 const ulint *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/** Builds an update vector from those fields, excluding the roll ptr and
184trx id fields, which in an index entry differ from a record that has
185the equal ordering fields. NOTE: we compare the fields as binary strings!
186@param[in] index clustered index
187@param[in] entry clustered index entry to insert
188@param[in] rec clustered index record
189@param[in] offsets rec_get_offsets(rec,index), or NULL
190@param[in] no_sys skip the system columns
191 DB_TRX_ID and DB_ROLL_PTR
192@param[in] trx transaction (for diagnostics),
193 or NULL
194@param[in] heap memory heap from which allocated
195@param[in] mysql_table NULL, or mysql table object when
196 user thread invokes dml
197@param[out] error error number in case of failure
198@return own: update vector of differing fields, excluding roll ptr and
199trx id */
201 dict_index_t *index, const dtuple_t *entry, const rec_t *rec,
202 const ulint *offsets, bool no_sys, trx_t *trx, mem_heap_t *heap,
203 TABLE *mysql_table, dberr_t *error);
204
205/** Replaces the new column values stored in the update vector to the index
206 entry given.
207@param[in,out] entry Index entry where replaced; the clustered index record must
208be covered by a lock or a page latch to prevent deletion [rollback or purge]
209@param[in] index Index; note that this may also be a non-clustered index
210@param[in] update An update vector built for the index so that the field number
211in an upd_field is the index position
212@param[in] order_only If true, limit the replacement to ordering fields of
213index; note that this does not work for non-clustered indexes.
214@param[in] heap Memory heap for allocating and copying the new values */
216 const dict_index_t *index,
217 const upd_t *update,
218 bool order_only,
219 mem_heap_t *heap);
220
221/** Replaces the new column values stored in the update vector to the index
222 entry given.
223@param[in,out] entry Index entry where replaced; the clustered index record must
224be covered by a lock or a page latch to prevent deletion (rollback or purge)
225@param[in] index Index; note that this may also be a non-clustered index
226@param[in] update An update vector built for the clustered index so that the
227field number in an upd_field is the clustered index position
228@param[in] heap Memory heap for allocating and copying the new values */
230 const dict_index_t *index,
231 const upd_t *update, mem_heap_t *heap);
232
233/** Replaces the new column values stored in the update vector.
234@param[in,out] row Row where replaced, indexed by col_no; the clustered index
235record must be covered by a lock or a page latch to prevent deletion (rollback
236or purge)
237@param[in,out] ext Null, or externally stored column prefixes
238@param[in] index Clustered index
239@param[in] update An update vector built for the clustered index
240@param[in] heap Memory heap */
241void row_upd_replace(dtuple_t *row, row_ext_t **ext, const dict_index_t *index,
242 const upd_t *update, mem_heap_t *heap);
243
244/** Replaces the virtual column values stored in a dtuple with that of
245a update vector.
246@param[in,out] row dtuple whose column to be updated
247@param[in] table table
248@param[in] update an update vector built for the clustered index
249@param[in] upd_new update to new or old value
250@param[in,out] undo_row undo row (if needs to be updated)
251@param[in] ptr remaining part in update undo log */
253 const upd_t *update, bool upd_new, dtuple_t *undo_row,
254 const byte *ptr);
255
256/** Checks if an update vector changes an ordering field of an index record.
257It will also help check if any non-multi-value field on the multi-value index
258gets updated or not.
259
260This function is fast if the update vector is short or the number of ordering
261fields in the index is small. Otherwise, this can be quadratic.
262NOTE: we compare the fields as binary strings!
263@param[in] index index of the record
264@param[in] update update vector for the row; NOTE: the
265 field numbers in this MUST be clustered index
266 positions!
267@param[in] thr query thread, or NULL
268@param[in] row old value of row, or NULL if the
269 row and the data values in update are not
270 known when this function is called, e.g., at
271 compile time
272@param[in] ext NULL, or prefixes of the externally
273 stored columns in the old row
274@param[in,out] non_mv_upd NULL, or not NULL pointer to get the
275 information about whether any non-multi-value
276 field on the multi-value index gets updated
277@param[in] flag ROW_BUILD_NORMAL, ROW_BUILD_FOR_PURGE or
278 ROW_BUILD_FOR_UNDO
279@return true if update vector changes an ordering field in the index record */
281 dict_index_t *index, const upd_t *update,
282 IF_DEBUG(const que_thr_t *thr, ) const dtuple_t *row, const row_ext_t *ext,
283 bool *non_mv_upd, ulint flag);
284
286 dict_index_t *index, const upd_t *update,
287 const que_thr_t *thr [[maybe_unused]], const dtuple_t *row,
288 const row_ext_t *ext, bool *non_mv_upd) {
290 index, update, IF_DEBUG(thr, ) row, ext, non_mv_upd, 0);
291}
292
293/** Checks if an FTS indexed column is affected by an UPDATE.
294 @return offset within fts_t::indexes if FTS indexed column updated else
295 ULINT_UNDEFINED */
297 dict_table_t *table, /*!< in: table */
298 upd_field_t *upd_field); /*!< in: field to check */
299/** Checks if an FTS Doc ID column is affected by an UPDATE.
300 @return whether Doc ID column is affected */
301[[nodiscard]] bool row_upd_changes_doc_id(
302 dict_table_t *table, /*!< in: table */
303 upd_field_t *upd_field); /*!< in: field to check */
304/** Checks if an update vector changes an ordering field of an index record.
305 This function is fast if the update vector is short or the number of ordering
306 fields in the index is small. Otherwise, this can be quadratic.
307 NOTE: we compare the fields as binary strings!
308 @return true if update vector may change an ordering field in an index
309 record */
311 const dict_table_t *table, /*!< in: table */
312 const upd_t *update); /*!< in: update vector for the row */
313
314/** Stores to the heap the row on which the node->pcur is positioned.
315@param[in] node row update node
316@param[in] thd mysql thread handle
317@param[in,out] mysql_table NULL, or mysql table object when
318 user thread invokes dml */
319void row_upd_store_row(upd_node_t *node, THD *thd, TABLE *mysql_table);
320
321/** Updates a row in a table. This is a high-level function used
322 in SQL execution graphs.
323 @return query thread to run next or NULL */
324que_thr_t *row_upd_step(que_thr_t *thr); /*!< in: query thread */
325/** Parses the log data of system field values.
326 @return log data end or NULL */
327byte *row_upd_parse_sys_vals(const byte *ptr, /*!< in: buffer */
328 const byte *end_ptr, /*!< in: buffer end */
329 ulint *pos, /*!< out: TRX_ID position in record */
330 trx_id_t *trx_id, /*!< out: trx id */
331 roll_ptr_t *roll_ptr); /*!< out: roll ptr */
332
333/** Updates the trx id and roll ptr field in a clustered index record in
334 database recovery.
335@param[in,out] rec Record
336@param[in,out] page_zip Compressed page, or null
337@param[in] offsets Array returned by rec_get_offsets()
338@param[in] pos Trx_id position in rec
339@param[in] trx_id Transaction id
340@param[in] roll_ptr Roll ptr of the undo log record */
342 const ulint *offsets, ulint pos,
343 trx_id_t trx_id, roll_ptr_t roll_ptr);
344
345/** Parses the log data written by row_upd_index_write_log.
346 @return log data end or NULL */
347byte *row_upd_index_parse(const byte *ptr, /*!< in: buffer */
348 const byte *end_ptr, /*!< in: buffer end */
349 mem_heap_t *heap, /*!< in: memory heap where update
350 vector is built */
351 upd_t **update_out); /*!< out: update vector */
352
353/** Get the new autoinc counter from the update vector when there is
354an autoinc field defined in this table.
355@param[in] update update vector for the clustered index
356@param[in] autoinc_field_no autoinc field's order in clustered index
357@return the new counter if we find it in the update vector, otherwise 0.
358We don't mind that the new counter happens to be 0, we just care about
359non-zero counters. */
361 ulint autoinc_field_no);
362
363/** This structure is used for undo logging of LOB index changes. */
367
368 /** Print the current object into the given output stream.
369 @param[in,out] out the output stream.
370 @return the output stream. */
371 std::ostream &print(std::ostream &out) const {
372 out << "[lob_index_diff_t: m_modifier_trxid=" << m_modifier_trxid
373 << ", m_modifier_undo_no=" << m_modifier_undo_no << "]";
374 return (out);
375 }
376};
377
379 std::vector<lob_index_diff_t, mem_heap_allocator<lob_index_diff_t>>;
380
381/** Overloading the global output operator to print lob_index_diff_t object.
382@param[in,out] out the output stream.
383@param[in] obj the object to be printed.
384@return the output stream.*/
385inline std::ostream &operator<<(std::ostream &out,
386 const lob_index_diff_t &obj) {
387 return (obj.print(out));
388}
389
390/** The modification done to the LOB. */
391struct Lob_diff {
392 /** Constructor.
393 @param[in] mem_heap the memory heap in which this object
394 has been created. */
395 Lob_diff(mem_heap_t *mem_heap) : heap(mem_heap) {
396 m_idx_diffs = static_cast<Lob_index_diff_vec *>(
398 new (m_idx_diffs)
400 }
401
402 /** Read the offset from the undo record.
403 @param[in] undo_ptr pointer into the undo log record.
404 @return pointer into the undo log record after offset. */
405 const byte *read_offset(const byte *undo_ptr) {
406 /* Read the offset. */
408 return (undo_ptr);
409 }
410
411 /** Read the length from the undo record.
412 @param[in] undo_ptr pointer into the undo log record.
413 @return pointer into the undo log record after length information. */
414 const byte *read_length(const byte *undo_ptr) {
415 /* Read the length. */
418
419 return (undo_ptr);
420 }
421
422 void set_old_data(const byte *undo_ptr) { m_old_data = undo_ptr; }
423
424 std::ostream &print(std::ostream &out) const {
425 out << "[Lob_diff: offset=" << m_offset << ", length=" << m_length;
426 if (m_old_data == nullptr) {
427 out << ", m_old_data=nullptr";
428 } else {
429 out << ", m_old_data=" << PrintBuffer(m_old_data, m_length);
430 }
431
432 if (m_idx_diffs != nullptr) {
433 for (auto iter = m_idx_diffs->begin(); iter != m_idx_diffs->end();
434 ++iter) {
435 out << *iter;
436 }
437 }
438
439 out << "]";
440 return (out);
441 }
442
443 /** The offset within LOB where partial update happened. */
445
446 /** The length of the modification. */
448
449 /** Changes to the LOB data. */
450 const byte *m_old_data = nullptr;
451
452 /** Changes to the LOB index. */
454
455 /** Memory heap in which this object is allocated. */
457};
458
459using Lob_diff_vector = std::vector<Lob_diff, mem_heap_allocator<Lob_diff>>;
460
461inline std::ostream &operator<<(std::ostream &out, const Lob_diff &obj) {
462 return (obj.print(out));
463}
464
465/* Update vector field */
468 : field_no(0),
469 orig_len(0),
470 exp(nullptr),
473 ext_in_old(false),
476 lob_version(0),
477 last_trx_id(0),
478 last_undo_no(0),
479 heap(nullptr) {}
480
481 bool is_virtual() const { return (new_val.is_virtual()); }
482
483 unsigned field_no : 16; /*!< field number in an index, usually
484 the clustered index, but in updating
485 a secondary index record in btr0cur.cc
486 this is the position in the secondary
487 index, also it could be the position
488 in virtual index for virtual column */
490 unsigned orig_len : 16; /*!< original length of the locally
491 stored part of an externally stored
492 column, or 0 */
493 que_node_t *exp; /*!< expression for calculating a new
494 value: it refers to column values and
495 constants in the symbol table of the
496 query graph */
497 dfield_t old_val; /*!< old value for the column */
498 dfield_t new_val; /*!< new value for the column */
499 dfield_t *old_v_val; /*!< old value for the virtual column */
500
501 Field *mysql_field; /*!< the mysql field object. */
502
503 /** If true, the field was stored externally in the old row. */
505
506 void push_lob_diff(const Lob_diff &lob_diff) {
507 if (lob_diffs == nullptr) {
508 lob_diffs = static_cast<Lob_diff_vector *>(
511 }
512 lob_diffs->push_back(lob_diff);
513 }
514
515 /** List of changes done to this updated field. This is usually
516 populated from the undo log. */
518
519 /** The LOB first page number. This information is read from
520 the undo log. */
522
524
525 /** The last trx that modified the LOB. */
527
528 /** The last stmt within trx that modified the LOB. */
530
531 std::ostream &print(std::ostream &out) const;
532
533 /** Empty the information collected on LOB diffs. */
534 void reset() {
535 if (lob_diffs != nullptr) {
536 lob_diffs->clear();
537 }
538 }
539
540 /** Memory heap in which this object is allocated. */
542};
543
544inline std::ostream &operator<<(std::ostream &out, const upd_field_t &obj) {
545 return (obj.print(out));
546}
547
548/* check whether an update field is on virtual column */
549static inline bool upd_fld_is_virtual_col(const upd_field_t *upd_fld) {
550 return (upd_fld->new_val.type.prtype & DATA_VIRTUAL) == DATA_VIRTUAL;
551}
552
553/* check whether an update field is on multi-value virtual column */
554static inline bool upd_fld_is_multi_value_col(const upd_field_t *upd_fld) {
555 return dfield_is_multi_value(&upd_fld->new_val);
556}
557
558/* set DATA_VIRTUAL bit on update field to show it is a virtual column */
559static inline void upd_fld_set_virtual_col(upd_field_t *upd_fld) {
560 upd_fld->new_val.type.prtype |= DATA_VIRTUAL;
561}
562
563/* Update vector structure */
564struct upd_t {
565 /** Heap from which memory allocated. This is not a new heap, rather
566 will point to other heap. Therefore memory allocated from this heap
567 is released when the pointed heap is freed or emptied. */
569
570 /** Heap from which memory is allocated if required only for current
571 statement. This heap is emtied at the end of statement from inside
572 ha_innobase::end_stmt(). */
574
575 /** New value of info bits to record; default is 0. */
577
578 /** Pointer to old row, used for virtual column update now. */
580
581 /** The table object. */
583
584 /** The mysql table object. */
586
587 /** Number of update fields. */
589
590 /** Array of update fields. */
592
593 /** Append an update field to the end of array
594 @param[in] field an update field */
595 void append(const upd_field_t &field) { fields[n_fields++] = field; }
596
597 /** Determine if the given field_no is modified.
598 @return true if modified, false otherwise. */
599 bool is_modified(const ulint field_no) const {
600 if (table == nullptr) {
601 ut_d(ut_error);
602 ut_o(return false);
603 }
604
605 return (get_field_by_field_no(field_no, table->first_index()) != nullptr);
606 }
607
608 /** Reset the update fields. */
609 void reset() {
610 for (ulint i = 0; i < n_fields; ++i) {
611 fields[i].reset();
612 }
613 }
614
615#ifdef UNIV_DEBUG
616 bool validate() const {
617 for (ulint i = 0; i < n_fields; ++i) {
618 dfield_t *field = &fields[i].new_val;
619 if (dfield_is_ext(field)) {
621 }
622 }
623 return (true);
624 }
625#endif // UNIV_DEBUG
626
627 /** Check if the given field number is partially updated.
628 @param[in] field_no the field number.
629 @return true if partially updated, false otherwise. */
630 bool is_partially_updated(ulint field_no) const;
631
632 upd_field_t *get_field_by_field_no(ulint field_no, dict_index_t *index) const;
633
635
636 /** Calculate the total number of bytes modified in one BLOB.
637 @param[in] bdv the binary diff vector containing all the
638 modifications to one BLOB.
639 @return the total modified bytes. */
641 size_t total = 0;
642 for (const Binary_diff &bdiff : bdv) {
643 total += bdiff.length();
644 }
645 return (total);
646 }
647
648 /** Empty the per_stmt_heap. */
650 if (per_stmt_heap != nullptr) {
652 }
653 }
654
655 /** Free the per_stmt_heap. */
657 if (per_stmt_heap != nullptr) {
659 per_stmt_heap = nullptr;
660 }
661 }
662
663 std::ostream &print(std::ostream &out) const;
664
665 /** Print the partial update vector (puvect) of the given update
666 field.
667 @param[in,out] out the output stream
668 @param[in] uf the updated field.
669 @return the output stream. */
670 std::ostream &print_puvect(std::ostream &out, upd_field_t *uf) const;
671};
672
673#ifdef UNIV_DEBUG
674/** Print the given binary diff into the given output stream.
675@param[in] out the output stream
676@param[in] bdiff binary diff to be printed.
677@param[in] table the table dictionary object.
678@param[in] field mysql field object.
679@param[in] print_old prints old data of the updated field
680@return the output stream */
681std::ostream &print_binary_diff(std::ostream &out, const Binary_diff *bdiff,
682 const dict_table_t *table, const Field *field,
683 bool print_old);
684
685std::ostream &print_binary_diff(std::ostream &out, const Binary_diff *bdiff);
686
687inline std::ostream &operator<<(std::ostream &out, const upd_t &obj) {
688 return (obj.print(out));
689}
690
691inline std::ostream &operator<<(std::ostream &out, const Binary_diff_vector &) {
692 return (out);
693}
694#endif /* UNIV_DEBUG */
695
696#ifndef UNIV_HOTBACKUP
697/* Update node structure which also implements the delete operation
698of a row */
699
701 que_common_t common; /*!< node type: QUE_NODE_UPDATE */
702 bool is_delete; /* true if delete, false if update */
704 /* true if searched update, false if
705 positioned */
707 /* true if the update node was created
708 for the MySQL interface */
709 dict_foreign_t *foreign; /* NULL or pointer to a foreign key
710 constraint if this update node is used in
711 doing an ON DELETE or ON UPDATE operation */
712 upd_node_t *cascade_node; /* NULL or an update node template which
713 is used to implement ON DELETE/UPDATE CASCADE
714 or ... SET NULL for foreign keys */
716 /*!< NULL or a mem heap where cascade_upd_nodes
717 are created.*/
718 sel_node_t *select; /*!< query graph subtree implementing a base
719 table cursor: the rows returned will be
720 updated */
721 btr_pcur_t *pcur; /*!< persistent cursor placed on the clustered
722 index record which should be updated or
723 deleted; the cursor is stored in the graph
724 of 'select' field above, except in the case
725 of the MySQL interface */
726 dict_table_t *table; /*!< table where updated */
727 upd_t *update; /*!< update vector for the row */
729 /* when this struct is used to implement
730 a cascade operation for foreign keys, we store
731 here the size of the buffer allocated for use
732 as the update vector */
733 sym_node_list_t columns; /* symbol table nodes for the columns
734 to retrieve from the table */
736 /* true if the select which retrieves the
737 records to update already sets an x-lock on
738 the clustered record; note that it must always
739 set at least an s-lock */
740 ulint cmpl_info; /* information extracted during query
741 compilation; speeds up execution:
742 UPD_NODE_NO_ORD_CHANGE and
743 UPD_NODE_NO_SIZE_CHANGE, ORed */
744 /*----------------------*/
745 /* Local storage for this graph node */
746 ulint state; /*!< node execution state */
747 dict_index_t *index; /*!< NULL, or the next index whose record should
748 be updated */
749 dtuple_t *row; /*!< NULL, or a copy (also fields copied to
750 heap) of the row to update; this must be reset
751 to NULL after a successful update */
752 row_ext_t *ext; /*!< NULL, or prefixes of the externally
753 stored columns in the old row */
754 dtuple_t *upd_row; /* NULL, or a copy of the updated row */
755 row_ext_t *upd_ext; /* NULL, or prefixes of the externally
756 stored columns in upd_row */
757 mem_heap_t *heap; /*!< memory heap used as auxiliary storage;
758 this must be emptied after a successful
759 update */
760 /*----------------------*/
761 sym_node_t *table_sym; /* table node in symbol table */
763 /* column assignment list */
764
765 /** When there is a lock wait error, this remembers current position of
766 the multi-value field, before which the values have been deleted.
767 This will be used for both DELETE and the delete phase of UPDATE. */
769
770 /** When there is a lock wait error, this remembers current position of
771 the multi-value field, before which the values have been updated. */
773
775};
776
777constexpr uint32_t UPD_NODE_MAGIC_N = 1579975;
778
779/* Node execution states */
780/** execution came to the node from a node above and if the field
781has_clust_rec_x_lock is false, we should set an intention x-lock on the table
782 */
783constexpr uint32_t UPD_NODE_SET_IX_LOCK = 1;
784/** clustered index record should be updated */
785constexpr uint32_t UPD_NODE_UPDATE_CLUSTERED = 2;
786/* clustered index record should be inserted, old record is already delete
787 marked */
788constexpr uint32_t UPD_NODE_INSERT_CLUSTERED = 3;
789/** an ordering field of the clustered index record was changed, or this is a
790 delete operation: should update all the secondary index records */
791constexpr uint32_t UPD_NODE_UPDATE_ALL_SEC = 5;
792/** secondary index entries should be looked at and updated if an ordering field
793 changed */
794constexpr uint32_t UPD_NODE_UPDATE_SOME_SEC = 6;
795
796/* Compilation info flags: these must fit within 2 bits; see trx0rec.h */
797/** no secondary index record will be changed in the update and no ordering
798 field of the clustered index */
799constexpr uint32_t UPD_NODE_NO_ORD_CHANGE = 1;
800/** no record field size will be changed in the update */
801constexpr uint32_t UPD_NODE_NO_SIZE_CHANGE = 2;
802#endif /* !UNIV_HOTBACKUP */
803
804#include "row0upd.ic"
805
806#endif
uint32_t page_no_t
Page number.
Definition: api0api.h:48
The index tree persistent cursor.
The index tree general types.
constexpr uint32_t BTR_EXTERN_FIELD_REF_SIZE
The size of a reference to data stored on a different page.
Definition: btr0types.h:65
Class that represents a single change to a column value in partial update of a JSON column.
Definition: table.h:1311
Definition: field.h:575
A typesafe replacement for DYNAMIC_ARRAY.
Definition: mem_root_array.h:425
For each client connection we create a separate thread with THD serving as a thread/connection descri...
Definition: sql_lexer_thd.h:33
A C++ wrapper class to the mem_heap_t routines, so that it can be used as an STL allocator.
Definition: mem0mem.h:355
SQL data field and tuple.
static uint32_t dfield_get_len(const dfield_t *field)
Gets length of field data.
static bool dfield_is_ext(const dfield_t *field)
Determines if a field is externally stored.
static bool dfield_is_multi_value(const dfield_t *field)
Determine if a field is of multi-value type.
constexpr uint32_t DATA_VIRTUAL
Virtual column.
Definition: data0type.h:222
dberr_t
Definition: db0err.h:38
Data dictionary global types.
Fido Client Authentication nullptr
Definition: fido_client_plugin.cc:221
constexpr page_no_t FIL_NULL
'null' (undefined) page offset in the context of file spaces
Definition: fil0fil.h:1118
static int flag
Definition: hp_test1.cc:39
#define UINT16_MAX
Definition: lexyy.cc:83
Implements the large objects (LOB) module.
static uint32_t mach_read_next_compressed(const byte **b)
Read a 32-bit integer in a compressed form.
static void * mem_heap_alloc(mem_heap_t *heap, ulint n)
Allocates n bytes of memory from a memory heap.
static void mem_heap_free(mem_heap_t *heap)
Frees the space occupied by a memory heap.
static void mem_heap_empty(mem_heap_t *heap)
Empties a memory heap.
static uint update
Definition: myisamlog.cc:93
Log error(cerr, "ERROR")
Type total(const Shards< COUNT > &shards) noexcept
Get the total value of all shards.
Definition: ut0counter.h:332
static PFS_engine_table_share_proxy table
Definition: pfs.cc:60
Json_data_extension ext
Definition: backend.cc:50
SQL parser global types.
Query graph global types.
void que_node_t
Definition: que0types.h:40
byte rec_t
Definition: rem0types.h:40
required string type
Definition: replication_group_member_actions.proto:33
Row operation global types.
upd_t * row_upd_build_difference_binary(dict_index_t *index, const dtuple_t *entry, const rec_t *rec, const ulint *offsets, bool no_sys, trx_t *trx, mem_heap_t *heap, TABLE *mysql_table, dberr_t *error)
Builds an update vector from those fields, excluding the roll ptr and trx id fields,...
Definition: row0upd.cc:832
constexpr uint32_t UPD_NODE_UPDATE_SOME_SEC
secondary index entries should be looked at and updated if an ordering field changed
Definition: row0upd.h:794
byte * row_upd_index_parse(const byte *ptr, const byte *end_ptr, mem_heap_t *heap, upd_t **update_out)
Parses the log data written by row_upd_index_write_log.
Definition: row0upd.cc:680
static void upd_field_set_field_no(upd_field_t *upd_field, ulint field_no, const dict_index_t *index)
Sets an index field number to be updated by an update vector field.
static ulint upd_get_n_fields(const upd_t *update)
Returns the number of fields in the update vector == number of columns to be updated by an update vec...
bool row_upd_changes_some_index_ord_field_binary(const dict_table_t *table, const upd_t *update)
Checks if an update vector changes an ordering field of an index record.
Definition: row0upd.cc:1656
static void upd_fld_set_virtual_col(upd_field_t *upd_fld)
Definition: row0upd.h:559
static void upd_field_set_v_field_no(upd_field_t *upd_field, ulint field_no, const dict_index_t *index)
set field number to a update vector field, marks this field is updated
bool row_upd_changes_field_size_or_external(const dict_index_t *index, const ulint *offsets, const upd_t *update)
Returns true if row update changes size of some field in index or if some field to be updated is stor...
Definition: row0upd.cc:358
void row_upd_index_write_log(dict_index_t *index, const upd_t *update, byte *log_ptr, mtr_t *mtr)
Writes to the redo log the new values of the fields occurring in the index.
Definition: row0upd.cc:595
static bool upd_fld_is_multi_value_col(const upd_field_t *upd_fld)
Definition: row0upd.h:554
std::vector< lob_index_diff_t, mem_heap_allocator< lob_index_diff_t > > Lob_index_diff_vec
Definition: row0upd.h:379
constexpr uint32_t UPD_NODE_MAGIC_N
Definition: row0upd.h:777
std::vector< Lob_diff, mem_heap_allocator< Lob_diff > > Lob_diff_vector
Definition: row0upd.h:459
constexpr uint32_t UPD_NODE_NO_ORD_CHANGE
no secondary index record will be changed in the update and no ordering field of the clustered index
Definition: row0upd.h:799
void row_upd_replace(dtuple_t *row, row_ext_t **ext, const dict_index_t *index, const upd_t *update, mem_heap_t *heap)
Replaces the new column values stored in the update vector.
Definition: row0upd.cc:1362
static bool row_upd_changes_ord_field_binary(dict_index_t *index, const upd_t *update, const que_thr_t *thr, const dtuple_t *row, const row_ext_t *ext, bool *non_mv_upd)
Definition: row0upd.h:285
static const upd_field_t * upd_get_field_by_field_no(const upd_t *update, ulint no, bool is_virtual)
Returns a field of an update vector by field_no.
void row_upd_index_entry_sys_field(dtuple_t *entry, dict_index_t *index, ulint type, uint64_t val)
Sets the trx id or roll ptr field of a clustered index entry.
Definition: row0upd.cc:332
constexpr uint32_t UPD_NODE_UPDATE_CLUSTERED
clustered index record should be updated
Definition: row0upd.h:785
upd_node_t * upd_node_create(mem_heap_t *heap)
Creates an update node for a query graph.
Definition: row0upd.cc:282
static upd_t * upd_create(ulint n, mem_heap_t *heap)
Creates an update vector object.
void row_upd_store_row(upd_node_t *node, THD *thd, TABLE *mysql_table)
Stores to the heap the row on which the node->pcur is positioned.
Definition: row0upd.cc:1920
bool row_upd_changes_disowned_external(const upd_t *update)
Returns true if row update contains disowned external fields.
Definition: row0upd.cc:438
constexpr uint32_t UPD_NODE_INSERT_CLUSTERED
Definition: row0upd.h:788
byte * row_upd_parse_sys_vals(const byte *ptr, const byte *end_ptr, ulint *pos, trx_id_t *trx_id, roll_ptr_t *roll_ptr)
Parses the log data of system field values.
Definition: row0upd.cc:570
que_thr_t * row_upd_step(que_thr_t *thr)
Updates a row in a table.
Definition: row0upd.cc:3241
static upd_field_t * upd_get_nth_field(const upd_t *update, ulint n)
Returns the nth field of an update vector.
void row_upd_index_replace_new_col_vals(dtuple_t *entry, const dict_index_t *index, const upd_t *update, mem_heap_t *heap)
Replaces the new column values stored in the update vector to the index entry given.
Definition: row0upd.cc:1174
byte * row_upd_write_sys_vals_to_log(dict_index_t *index, trx_id_t trx_id, roll_ptr_t roll_ptr, byte *log_ptr, mtr_t *mtr)
Writes into the redo log the values of trx id and roll ptr and enough info to determine their positio...
Definition: row0upd.cc:550
static void row_upd_rec_sys_fields(rec_t *rec, page_zip_des_t *page_zip, const dict_index_t *index, const ulint *offsets, const trx_t *trx, roll_ptr_t roll_ptr)
Updates the trx id and roll ptr field in a clustered index record when a row is updated or marked del...
constexpr uint32_t UPD_NODE_UPDATE_ALL_SEC
an ordering field of the clustered index record was changed, or this is a delete operation: should up...
Definition: row0upd.h:791
std::ostream & print_binary_diff(std::ostream &out, const Binary_diff *bdiff, const dict_table_t *table, const Field *field, bool print_old)
Print the given binary diff into the given output stream.
Definition: row0upd.cc:3368
ulint row_upd_changes_fts_column(dict_table_t *table, upd_field_t *upd_field)
Checks if an FTS indexed column is affected by an UPDATE.
Definition: row0upd.cc:1706
constexpr uint32_t UPD_NODE_SET_IX_LOCK
execution came to the node from a node above and if the field has_clust_rec_x_lock is false,...
Definition: row0upd.h:783
std::ostream & operator<<(std::ostream &out, const lob_index_diff_t &obj)
Overloading the global output operator to print lob_index_diff_t object.
Definition: row0upd.h:385
void row_upd_rec_sys_fields_in_recovery(rec_t *rec, page_zip_des_t *page_zip, const ulint *offsets, ulint pos, trx_id_t trx_id, roll_ptr_t roll_ptr)
Updates the trx id and roll ptr field in a clustered index record in database recovery.
Definition: row0upd.cc:305
constexpr uint32_t UPD_NODE_NO_SIZE_CHANGE
no record field size will be changed in the update
Definition: row0upd.h:801
upd_t * row_upd_build_sec_rec_difference_binary(const rec_t *rec, dict_index_t *index, const ulint *offsets, const dtuple_t *entry, mem_heap_t *heap)
Builds an update vector from those fields which in a secondary index entry differ from a record that ...
Definition: row0upd.cc:757
void row_upd_rec_in_place(rec_t *rec, const dict_index_t *index, const ulint *offsets, const upd_t *update, page_zip_des_t *page_zip)
Replaces the new column values stored in the update vector to the record given.
Definition: row0upd.cc:474
static bool upd_fld_is_virtual_col(const upd_field_t *upd_fld)
Definition: row0upd.h:549
void row_upd_replace_vcol(dtuple_t *row, const dict_table_t *table, const upd_t *update, bool upd_new, dtuple_t *undo_row, const byte *ptr)
Replaces the virtual column values stored in a dtuple with that of a update vector.
Definition: row0upd.cc:1233
uint64_t row_upd_get_new_autoinc_counter(const upd_t *update, ulint autoinc_field_no)
Get the new autoinc counter from the update vector when there is an autoinc field defined in this tab...
Definition: row0upd.cc:2700
void row_upd_index_replace_new_col_vals_index_pos(dtuple_t *entry, const dict_index_t *index, const upd_t *update, bool order_only, mem_heap_t *heap)
Replaces the new column values stored in the update vector to the index entry given.
Definition: row0upd.cc:1116
bool row_upd_changes_doc_id(dict_table_t *table, upd_field_t *upd_field)
Checks if an FTS Doc ID column is affected by an UPDATE.
Definition: row0upd.cc:1686
bool row_upd_changes_ord_field_binary_func(dict_index_t *index, const upd_t *update, const que_thr_t *thr, const dtuple_t *row, const row_ext_t *ext, bool *non_mv_upd, ulint flag)
Checks if an update vector changes an ordering field of an index record.
Definition: row0upd.cc:1429
Update of a row.
TempTable Table declarations.
The modification done to the LOB.
Definition: row0upd.h:391
std::ostream & print(std::ostream &out) const
Definition: row0upd.h:424
const byte * read_offset(const byte *undo_ptr)
Read the offset from the undo record.
Definition: row0upd.h:405
Lob_diff(mem_heap_t *mem_heap)
Constructor.
Definition: row0upd.h:395
const byte * m_old_data
Changes to the LOB data.
Definition: row0upd.h:450
mem_heap_t * heap
Memory heap in which this object is allocated.
Definition: row0upd.h:456
Lob_index_diff_vec * m_idx_diffs
Changes to the LOB index.
Definition: row0upd.h:453
const byte * read_length(const byte *undo_ptr)
Read the length from the undo record.
Definition: row0upd.h:414
ulint m_length
The length of the modification.
Definition: row0upd.h:447
void set_old_data(const byte *undo_ptr)
Definition: row0upd.h:422
ulint m_offset
The offset within LOB where partial update happened.
Definition: row0upd.h:444
Definition: ut.h:71
Definition: table.h:1394
Definition: completion_hash.h:34
Definition: btr0pcur.h:98
Structure for an SQL data field.
Definition: data0data.h:604
dtype_t type
type of data
Definition: data0data.h:611
bool is_virtual() const
Definition: data0data.h:613
Data structure for a foreign key constraint; an example: FOREIGN KEY (A, B) REFERENCES TABLE2 (C,...
Definition: dict0mem.h:1665
Data structure for an index.
Definition: dict0mem.h:1045
Data structure for a database table.
Definition: dict0mem.h:1908
const dict_index_t * first_index() const
Definition: dict0mem.h:2454
Structure for an SQL data tuple of fields (logical record)
Definition: data0data.h:681
unsigned prtype
precise type; MySQL data type, charset code, flags to indicate nullability, signedness,...
Definition: data0type.h:498
static const ulint LOB_SMALL_CHANGE_THRESHOLD
If the total number of bytes modified in an LOB, in an update operation, is less than or equal to thi...
Definition: lob0lob.h:209
This structure is used for undo logging of LOB index changes.
Definition: row0upd.h:364
undo_no_t m_modifier_undo_no
Definition: row0upd.h:366
trx_id_t m_modifier_trxid
Definition: row0upd.h:365
std::ostream & print(std::ostream &out) const
Print the current object into the given output stream.
Definition: row0upd.h:371
The info structure stored at the beginning of a heap block.
Definition: mem0mem.h:301
Mini-transaction handle and buffer.
Definition: mtr0mtr.h:176
Compressed page descriptor.
Definition: page0types.h:199
Definition: que0types.h:50
Definition: que0que.h:241
Prefixes of externally stored columns.
Definition: row0ext.h:94
Select statement node.
Definition: row0sel.h:328
Symbol table node.
Definition: pars0sym.h:112
Definition: trx0trx.h:685
Definition: row0upd.h:466
unsigned orig_len
original length of the locally stored part of an externally stored column, or 0
Definition: row0upd.h:490
dfield_t new_val
new value for the column
Definition: row0upd.h:498
undo_no_t last_undo_no
The last stmt within trx that modified the LOB.
Definition: row0upd.h:529
bool ext_in_old
If true, the field was stored externally in the old row.
Definition: row0upd.h:504
unsigned field_no
field number in an index, usually the clustered index, but in updating a secondary index record in bt...
Definition: row0upd.h:483
trx_id_t last_trx_id
The last trx that modified the LOB.
Definition: row0upd.h:526
void push_lob_diff(const Lob_diff &lob_diff)
Definition: row0upd.h:506
page_no_t lob_first_page_no
The LOB first page number.
Definition: row0upd.h:521
upd_field_t()
Definition: row0upd.h:467
dfield_t old_val
old value for the column
Definition: row0upd.h:497
std::ostream & print(std::ostream &out) const
Definition: row0upd.cc:3342
Field * mysql_field
the mysql field object.
Definition: row0upd.h:501
mem_heap_t * heap
Memory heap in which this object is allocated.
Definition: row0upd.h:541
que_node_t * exp
expression for calculating a new value: it refers to column values and constants in the symbol table ...
Definition: row0upd.h:493
Lob_diff_vector * lob_diffs
List of changes done to this updated field.
Definition: row0upd.h:517
uint16_t field_phy_pos
Definition: row0upd.h:489
bool is_virtual() const
Definition: row0upd.h:481
ulint lob_version
Definition: row0upd.h:523
dfield_t * old_v_val
old value for the virtual column
Definition: row0upd.h:499
void reset()
Empty the information collected on LOB diffs.
Definition: row0upd.h:534
Definition: row0upd.h:700
bool in_mysql_interface
Definition: row0upd.h:706
sym_node_list_t columns
Definition: row0upd.h:733
sym_node_t * table_sym
Definition: row0upd.h:761
dtuple_t * upd_row
Definition: row0upd.h:754
ulint update_n_fields
Definition: row0upd.h:728
dict_foreign_t * foreign
Definition: row0upd.h:709
dict_index_t * index
NULL, or the next index whose record should be updated.
Definition: row0upd.h:747
row_ext_t * ext
NULL, or prefixes of the externally stored columns in the old row.
Definition: row0upd.h:752
mem_heap_t * cascade_heap
NULL or a mem heap where cascade_upd_nodes are created.
Definition: row0upd.h:715
uint32_t del_multi_val_pos
When there is a lock wait error, this remembers current position of the multi-value field,...
Definition: row0upd.h:768
que_node_t * col_assign_list
Definition: row0upd.h:762
bool searched_update
Definition: row0upd.h:703
ulint state
node execution state
Definition: row0upd.h:746
upd_t * update
update vector for the row
Definition: row0upd.h:727
dict_table_t * table
table where updated
Definition: row0upd.h:726
sel_node_t * select
query graph subtree implementing a base table cursor: the rows returned will be updated
Definition: row0upd.h:718
btr_pcur_t * pcur
persistent cursor placed on the clustered index record which should be updated or deleted; the cursor...
Definition: row0upd.h:721
row_ext_t * upd_ext
Definition: row0upd.h:755
dtuple_t * row
NULL, or a copy (also fields copied to heap) of the row to update; this must be reset to NULL after a...
Definition: row0upd.h:749
que_common_t common
node type: QUE_NODE_UPDATE
Definition: row0upd.h:701
bool has_clust_rec_x_lock
Definition: row0upd.h:735
bool is_delete
Definition: row0upd.h:702
ulint magic_n
Definition: row0upd.h:774
uint32_t upd_multi_val_pos
When there is a lock wait error, this remembers current position of the multi-value field,...
Definition: row0upd.h:772
ulint cmpl_info
Definition: row0upd.h:740
mem_heap_t * heap
memory heap used as auxiliary storage; this must be emptied after a successful update
Definition: row0upd.h:757
upd_node_t * cascade_node
Definition: row0upd.h:712
Definition: row0upd.h:564
void append(const upd_field_t &field)
Append an update field to the end of array.
Definition: row0upd.h:595
static size_t get_total_modified_bytes(const Binary_diff_vector &bdv)
Calculate the total number of bytes modified in one BLOB.
Definition: row0upd.h:640
bool is_partially_updated(ulint field_no) const
Check if the given field number is partially updated.
Definition: row0upd.cc:3443
mem_heap_t * heap
Heap from which memory allocated.
Definition: row0upd.h:568
void free_per_stmt_heap()
Free the per_stmt_heap.
Definition: row0upd.h:656
bool validate() const
Definition: row0upd.h:616
void empty_per_stmt_heap()
Empty the per_stmt_heap.
Definition: row0upd.h:649
dtuple_t * old_vrow
Pointer to old row, used for virtual column update now.
Definition: row0upd.h:579
upd_field_t * fields
Array of update fields.
Definition: row0upd.h:591
ulint info_bits
New value of info bits to record; default is 0.
Definition: row0upd.h:576
mem_heap_t * per_stmt_heap
Heap from which memory is allocated if required only for current statement.
Definition: row0upd.h:573
const Binary_diff_vector * get_binary_diff_by_field_no(ulint field_no) const
Definition: row0upd.cc:3487
std::ostream & print(std::ostream &out) const
Definition: row0upd.cc:3358
dict_table_t * table
The table object.
Definition: row0upd.h:582
upd_field_t * get_field_by_field_no(ulint field_no, dict_index_t *index) const
Definition: row0upd.cc:3422
TABLE * mysql_table
The mysql table object.
Definition: row0upd.h:585
bool is_modified(const ulint field_no) const
Determine if the given field_no is modified.
Definition: row0upd.h:599
ulint n_fields
Number of update fields.
Definition: row0upd.h:588
void reset()
Reset the update fields.
Definition: row0upd.h:609
std::ostream & print_puvect(std::ostream &out, upd_field_t *uf) const
Print the partial update vector (puvect) of the given update field.
Definition: row0upd.cc:3404
Transaction system global type definitions.
ib_id_t undo_no_t
Undo number.
Definition: trx0types.h:141
ib_id_t trx_id_t
Transaction identifier (DB_TRX_ID, DATA_TRX_ID)
Definition: trx0types.h:137
ib_id_t roll_ptr_t
Rollback pointer (DB_ROLL_PTR, DATA_ROLL_PTR)
Definition: trx0types.h:139
Version control for database, common definitions, and include files.
#define IF_DEBUG(...)
Definition: univ.i:673
unsigned long int ulint
Definition: univ.i:405
#define ut_error
Abort execution.
Definition: ut0dbg.h:64
#define ut_ad(EXPR)
Debug assertion.
Definition: ut0dbg.h:68
#define ut_o(EXPR)
Opposite of ut_d().
Definition: ut0dbg.h:72
#define ut_d(EXPR)
Debug statement.
Definition: ut0dbg.h:70
int n
Definition: xcom_base.cc:508