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