MySQL  8.0.22
Source Code Documentation
row0upd.h
Go to the documentation of this file.
1 /*****************************************************************************
2 
3 Copyright (c) 1996, 2020, Oracle and/or its affiliates.
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.
126 @param[in,out] entry Index entry, where the memory buffers for sys fields are
127 already 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, ib_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. */
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 
209 /** Replaces the new column values stored in the update vector to the index
210  entry given.
211 @param[in,out] entry Index entry where replaced; the clustered index record must
212 be covered by a lock or a page latch to prevent deletion [rollback or purge]
213 @param[in] index Index; note that this may also be a non-clustered index
214 @param[in] update An update vector built for the index so that the field number
215 in an upd_field is the index position
216 @param[in] order_only If true, limit the replacement to ordering fields of
217 index; note that this does not work for non-clustered indexes.
218 @param[in] heap Memory heap for allocating and copying the new values */
220  const dict_index_t *index,
221  const upd_t *update,
222  ibool order_only,
223  mem_heap_t *heap);
224 
225 /** Replaces the new column values stored in the update vector to the index
226  entry given.
227 @param[in,out] entry Index entry where replaced; the clustered index record must
228 be covered by a lock or a page latch to prevent deletion (rollback or purge)
229 @param[in] index Index; note that this may also be a non-clustered index
230 @param[in] update An update vector built for the clustered index so that the
231 field number in an upd_field is the clustered index position
232 @param[in] heap Memory heap for allocating and copying the new values */
234  const dict_index_t *index,
235  const upd_t *update, mem_heap_t *heap);
236 
237 /** Replaces the new column values stored in the update vector.
238 @param[in] trx Current transaction.
239 @param[in,out] row Row where replaced, indexed by col_no; the clustered index
240 record must be covered by a lock or a page latch to prevent deletion (rollback
241 or purge)
242 @param[in,out] ext Null, or externally stored column prefixes
243 @param[in] index Clustered index
244 @param[in] update An update vector built for the clustered index
245 @param[in] heap Memory heap */
246 void row_upd_replace(trx_t *trx, dtuple_t *row, row_ext_t **ext,
247  const dict_index_t *index, const upd_t *update,
248  mem_heap_t *heap);
249 
250 /** Replaces the virtual column values stored in a dtuple with that of
251 a update vector.
252 @param[in,out] row dtuple whose column to be updated
253 @param[in] table table
254 @param[in] update an update vector built for the clustered index
255 @param[in] upd_new update to new or old value
256 @param[in,out] undo_row undo row (if needs to be updated)
257 @param[in] ptr remaining part in update undo log */
258 void row_upd_replace_vcol(dtuple_t *row, const dict_table_t *table,
259  const upd_t *update, bool upd_new, dtuple_t *undo_row,
260  const byte *ptr);
261 
262 /** Checks if an update vector changes an ordering field of an index record.
263 It will also help check if any non-multi-value field on the multi-value index
264 gets updated or not.
265 
266 This function is fast if the update vector is short or the number of ordering
267 fields in the index is small. Otherwise, this can be quadratic.
268 NOTE: we compare the fields as binary strings!
269 @param[in] index index of the record
270 @param[in] update update vector for the row; NOTE: the
271  field numbers in this MUST be clustered index
272  positions! */
273 #ifdef UNIV_DEBUG
274 /**
275 @param[in] thr query thread, or NULL */
276 #endif /* UNIV_DEBUG */
277 /**
278 @param[in] row old value of row, or NULL if the
279  row and the data values in update are not
280  known when this function is called, e.g., at
281  compile time
282 @param[in] ext NULL, or prefixes of the externally
283  stored columns in the old row
284 @param[in,out] non_mv_upd NULL, or not NULL pointer to get the
285  information about whether any non-multi-value
286  field on the multi-value index gets updated
287 @param[in] flag ROW_BUILD_NORMAL, ROW_BUILD_FOR_PURGE or
288  ROW_BUILD_FOR_UNDO
289 @return true if update vector changes an ordering field in the index record */
291  const upd_t *update,
292 #ifdef UNIV_DEBUG
293  const que_thr_t *thr,
294 #endif /* UNIV_DEBUG */
295  const dtuple_t *row,
296  const row_ext_t *ext,
297  bool *non_mv_upd, ulint flag)
298  MY_ATTRIBUTE((warn_unused_result));
299 
300 #ifdef UNIV_DEBUG
301 #define row_upd_changes_ord_field_binary(index, update, thr, row, ext, \
302  non_mv_upd) \
303  row_upd_changes_ord_field_binary_func(index, update, thr, row, ext, \
304  non_mv_upd, 0)
305 #else /* UNIV_DEBUG */
306 #define row_upd_changes_ord_field_binary(index, update, thr, row, ext, \
307  non_mv_upd) \
308  row_upd_changes_ord_field_binary_func(index, update, row, ext, non_mv_upd, 0)
309 #endif /* UNIV_DEBUG */
310 
311 /** Checks if an FTS indexed column is affected by an UPDATE.
312  @return offset within fts_t::indexes if FTS indexed column updated else
313  ULINT_UNDEFINED */
315  dict_table_t *table, /*!< in: table */
316  upd_field_t *upd_field); /*!< in: field to check */
317 /** Checks if an FTS Doc ID column is affected by an UPDATE.
318  @return whether Doc ID column is affected */
319 bool row_upd_changes_doc_id(dict_table_t *table, /*!< in: table */
320  upd_field_t *upd_field) /*!< in: field to check */
321  MY_ATTRIBUTE((warn_unused_result));
322 /** Checks if an update vector changes an ordering field of an index record.
323  This function is fast if the update vector is short or the number of ordering
324  fields in the index is small. Otherwise, this can be quadratic.
325  NOTE: we compare the fields as binary strings!
326  @return true if update vector may change an ordering field in an index
327  record */
329  const dict_table_t *table, /*!< in: table */
330  const upd_t *update); /*!< in: update vector for the row */
331 
332 /** Stores to the heap the row on which the node->pcur is positioned.
333 @param[in] trx the transaction object
334 @param[in] node row update node
335 @param[in] thd mysql thread handle
336 @param[in,out] mysql_table NULL, or mysql table object when
337  user thread invokes dml */
338 void row_upd_store_row(trx_t *trx, upd_node_t *node, THD *thd,
339  TABLE *mysql_table);
340 
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 
353 /** Updates the trx id and roll ptr field in a clustered index record in
354  database recovery.
355 @param[in,out] rec Record
356 @param[in,out] page_zip Compressed page, or null
357 @param[in] offsets Array returned by rec_get_offsets()
358 @param[in] pos Trx_id position in rec
359 @param[in] trx_id Transaction id
360 @param[in] roll_ptr Roll ptr of the undo log record */
362  const ulint *offsets, ulint pos,
363  trx_id_t trx_id, roll_ptr_t roll_ptr);
364 
365 /** Parses the log data written by row_upd_index_write_log.
366  @return log data end or NULL */
367 byte *row_upd_index_parse(const byte *ptr, /*!< in: buffer */
368  const byte *end_ptr, /*!< in: buffer end */
369  mem_heap_t *heap, /*!< in: memory heap where update
370  vector is built */
371  upd_t **update_out); /*!< out: update vector */
372 
373 /** Get the new autoinc counter from the update vector when there is
374 an autoinc field defined in this table.
375 @param[in] update update vector for the clustered index
376 @param[in] autoinc_field_no autoinc field's order in clustered index
377 @return the new counter if we find it in the update vector, otherwise 0.
378 We don't mind that the new counter happens to be 0, we just care about
379 non-zero counters. */
380 ib_uint64_t row_upd_get_new_autoinc_counter(const upd_t *update,
381  ulint autoinc_field_no);
382 
383 /** This structure is used for undo logging of LOB index changes. */
387 
388  /** Print the current object into the given output stream.
389  @param[in,out] out the output stream.
390  @return the output stream. */
391  std::ostream &print(std::ostream &out) const {
392  out << "[lob_index_diff_t: m_modifier_trxid=" << m_modifier_trxid
393  << ", m_modifier_undo_no=" << m_modifier_undo_no << "]";
394  return (out);
395  }
396 };
397 
398 using Lob_index_diff_vec =
399  std::vector<lob_index_diff_t, mem_heap_allocator<lob_index_diff_t>>;
400 
401 /** Overloading the global output operator to print lob_index_diff_t object.
402 @param[in,out] out the output stream.
403 @param[in] obj the object to be printed.
404 @return the output stream.*/
405 inline std::ostream &operator<<(std::ostream &out,
406  const lob_index_diff_t &obj) {
407  return (obj.print(out));
408 }
409 
410 /** The modification done to the LOB. */
411 struct Lob_diff {
412  /** Constructor.
413  @param[in] mem_heap the memory heap in which this object
414  has been created. */
415  Lob_diff(mem_heap_t *mem_heap) : heap(mem_heap) {
416  m_idx_diffs = static_cast<Lob_index_diff_vec *>(
417  mem_heap_alloc(heap, sizeof(Lob_index_diff_vec)));
418  new (m_idx_diffs)
420  }
421 
422  /** Read the offset from the undo record.
423  @param[in] undo_ptr pointer into the undo log record.
424  @return pointer into the undo log record after offset. */
425  const byte *read_offset(const byte *undo_ptr) {
426  /* Read the offset. */
427  m_offset = mach_read_next_compressed(&undo_ptr);
428  return (undo_ptr);
429  }
430 
431  /** Read the length from the undo record.
432  @param[in] undo_ptr pointer into the undo log record.
433  @return pointer into the undo log record after length information. */
434  const byte *read_length(const byte *undo_ptr) {
435  /* Read the length. */
436  m_length = mach_read_next_compressed(&undo_ptr);
438 
439  return (undo_ptr);
440  }
441 
442  void set_old_data(const byte *undo_ptr) { m_old_data = undo_ptr; }
443 
444  std::ostream &print(std::ostream &out) const {
445  out << "[Lob_diff: offset=" << m_offset << ", length=" << m_length;
446  if (m_old_data == nullptr) {
447  out << ", m_old_data=nullptr";
448  } else {
449  out << ", m_old_data=" << PrintBuffer(m_old_data, m_length);
450  }
451 
452  if (m_idx_diffs != nullptr) {
453  for (auto iter = m_idx_diffs->begin(); iter != m_idx_diffs->end();
454  ++iter) {
455  out << *iter;
456  }
457  }
458 
459  out << "]";
460  return (out);
461  }
462 
463  /** The offset within LOB where partial update happened. */
464  ulint m_offset = 0;
465 
466  /** The length of the modification. */
467  ulint m_length = 0;
468 
469  /** Changes to the LOB data. */
470  const byte *m_old_data = nullptr;
471 
472  /** Changes to the LOB index. */
474 
475  /** Memory heap in which this object is allocated. */
477 };
478 
479 using Lob_diff_vector = std::vector<Lob_diff, mem_heap_allocator<Lob_diff>>;
480 
481 inline std::ostream &operator<<(std::ostream &out, const Lob_diff &obj) {
482  return (obj.print(out));
483 }
484 
485 /* Update vector field */
486 struct upd_field_t {
488  : field_no(0),
489  orig_len(0),
490  exp(nullptr),
491  old_v_val(nullptr),
492  mysql_field(nullptr),
493  ext_in_old(false),
494  lob_diffs(nullptr),
495  lob_first_page_no(FIL_NULL),
496  lob_version(0),
497  last_trx_id(0),
498  last_undo_no(0),
499  heap(nullptr) {}
500 
501  bool is_virtual() const { return (new_val.is_virtual()); }
502 
503  unsigned field_no : 16; /*!< field number in an index, usually
504  the clustered index, but in updating
505  a secondary index record in btr0cur.cc
506  this is the position in the secondary
507  index, also it could be the position
508  in virtual index for virtual column */
509  unsigned orig_len : 16; /*!< original length of the locally
510  stored part of an externally stored
511  column, or 0 */
512  que_node_t *exp; /*!< expression for calculating a new
513  value: it refers to column values and
514  constants in the symbol table of the
515  query graph */
516  dfield_t old_val; /*!< old value for the column */
517  dfield_t new_val; /*!< new value for the column */
518  dfield_t *old_v_val; /*!< old value for the virtual column */
519 
520  Field *mysql_field; /*!< the mysql field object. */
521 
522  /** If true, the field was stored externally in the old row. */
524 
525  void push_lob_diff(const Lob_diff &lob_diff) {
526  if (lob_diffs == nullptr) {
527  lob_diffs = static_cast<Lob_diff_vector *>(
528  mem_heap_alloc(heap, sizeof(Lob_diff_vector)));
529  new (lob_diffs) Lob_diff_vector(mem_heap_allocator<Lob_diff>(heap));
530  }
531  lob_diffs->push_back(lob_diff);
532  }
533 
534  /** List of changes done to this updated field. This is usually
535  populated from the undo log. */
537 
538  /** The LOB first page number. This information is read from
539  the undo log. */
541 
542  ulint lob_version;
543 
544  /** The last trx that modified the LOB. */
546 
547  /** The last stmt within trx that modified the LOB. */
549 
550  std::ostream &print(std::ostream &out) const;
551 
552  /** Empty the information collected on LOB diffs. */
553  void reset() {
554  if (lob_diffs != nullptr) {
555  lob_diffs->clear();
556  }
557  }
558 
559  /** Memory heap in which this object is allocated. */
561 };
562 
563 inline std::ostream &operator<<(std::ostream &out, const upd_field_t &obj) {
564  return (obj.print(out));
565 }
566 
567 /* check whether an update field is on virtual column */
568 #define upd_fld_is_virtual_col(upd_fld) \
569  (((upd_fld)->new_val.type.prtype & DATA_VIRTUAL) == DATA_VIRTUAL)
570 
571 /* check whether an update field is on multi-value virtual column */
572 #define upd_fld_is_multi_value_col(upd_fld) \
573  (dfield_is_multi_value(&((upd_fld)->new_val)))
574 
575 /* set DATA_VIRTUAL bit on update field to show it is a virtual column */
576 #define upd_fld_set_virtual_col(upd_fld) \
577  ((upd_fld)->new_val.type.prtype |= DATA_VIRTUAL)
578 
579 /* Update vector structure */
580 struct upd_t {
581  mem_heap_t *heap; /*!< heap from which memory allocated */
582  ulint info_bits; /*!< new value of info bits to record;
583  default is 0 */
584  dtuple_t *old_vrow; /*!< pointer to old row, used for
585  virtual column update now */
586  dict_table_t *table; /*!< the table object */
587  TABLE *mysql_table; /*!< the mysql table object */
588 
589  ulint n_fields; /*!< number of update fields */
590  upd_field_t *fields; /*!< array of update fields */
591 
592  /** Append an update field to the end of array
593  @param[in] field an update field */
594  void append(const upd_field_t &field) { fields[n_fields++] = field; }
595 
596  /** Determine if the given field_no is modified.
597  @return true if modified, false otherwise. */
598  bool is_modified(const ulint field_no) const {
599  if (table == nullptr) {
600  ut_ad(false);
601  return false;
602  }
603 
604  return (get_field_by_field_no(field_no, table->first_index()) != nullptr);
605  }
606 
607  /** Reset the update fields. */
608  void reset() {
609  for (ulint i = 0; i < n_fields; ++i) {
610  fields[i].reset();
611  }
612  }
613 
614 #ifdef UNIV_DEBUG
615  bool validate() const {
616  for (ulint i = 0; i < n_fields; ++i) {
617  dfield_t *field = &fields[i].new_val;
618  if (dfield_is_ext(field)) {
620  }
621  }
622  return (true);
623  }
624 #endif // UNIV_DEBUG
625 
626  /** Check if the given field number is partially updated.
627  @param[in] field_no the field number.
628  @return true if partially updated, false otherwise. */
629  bool is_partially_updated(ulint field_no) const;
630 
631  upd_field_t *get_field_by_field_no(ulint field_no, dict_index_t *index) const;
632 
633  const Binary_diff_vector *get_binary_diff_by_field_no(ulint field_no) const;
634 
635  /** Calculate the total number of bytes modified in one BLOB.
636  @param[in] bdv the binary diff vector containing all the
637  modifications to one BLOB.
638  @return the total modified bytes. */
639  static size_t get_total_modified_bytes(const Binary_diff_vector &bdv) {
640  size_t total = 0;
641  for (const Binary_diff &bdiff : bdv) {
642  total += bdiff.length();
643  }
644  return (total);
645  }
646 
647  std::ostream &print(std::ostream &out) const;
648 
649  /** Print the partial update vector (puvect) of the given update
650  field.
651  @param[in,out] out the output stream
652  @param[in] uf the updated field.
653  @return the output stream. */
654  std::ostream &print_puvect(std::ostream &out, upd_field_t *uf) const;
655 };
656 
657 #ifdef UNIV_DEBUG
658 /** Print the given binary diff into the given output stream.
659 @param[in] out the output stream
660 @param[in] bdiff binary diff to be printed.
661 @param[in] table the table dictionary object.
662 @param[in] field mysql field object.
663 @return the output stream */
664 std::ostream &print_binary_diff(std::ostream &out, const Binary_diff *bdiff,
665  const dict_table_t *table, const Field *field);
666 
667 std::ostream &print_binary_diff(std::ostream &out, const Binary_diff *bdiff);
668 
669 inline std::ostream &operator<<(std::ostream &out, const upd_t &obj) {
670  return (obj.print(out));
671 }
672 
673 inline std::ostream &operator<<(std::ostream &out,
674  const Binary_diff_vector &obj) {
675  return (out);
676 }
677 #endif /* UNIV_DEBUG */
678 
679 #ifndef UNIV_HOTBACKUP
680 /* Update node structure which also implements the delete operation
681 of a row */
682 
683 struct upd_node_t {
684  que_common_t common; /*!< node type: QUE_NODE_UPDATE */
685  ibool is_delete; /* TRUE if delete, FALSE if update */
687  /* TRUE if searched update, FALSE if
688  positioned */
690  /* TRUE if the update node was created
691  for the MySQL interface */
692  dict_foreign_t *foreign; /* NULL or pointer to a foreign key
693  constraint if this update node is used in
694  doing an ON DELETE or ON UPDATE operation */
695  upd_node_t *cascade_node; /* NULL or an update node template which
696  is used to implement ON DELETE/UPDATE CASCADE
697  or ... SET NULL for foreign keys */
699  /*!< NULL or a mem heap where cascade_upd_nodes
700  are created.*/
701  sel_node_t *select; /*!< query graph subtree implementing a base
702  table cursor: the rows returned will be
703  updated */
704  btr_pcur_t *pcur; /*!< persistent cursor placed on the clustered
705  index record which should be updated or
706  deleted; the cursor is stored in the graph
707  of 'select' field above, except in the case
708  of the MySQL interface */
709  dict_table_t *table; /*!< table where updated */
710  upd_t *update; /*!< update vector for the row */
712  /* when this struct is used to implement
713  a cascade operation for foreign keys, we store
714  here the size of the buffer allocated for use
715  as the update vector */
716  sym_node_list_t columns; /* symbol table nodes for the columns
717  to retrieve from the table */
719  /* TRUE if the select which retrieves the
720  records to update already sets an x-lock on
721  the clustered record; note that it must always
722  set at least an s-lock */
723  ulint cmpl_info; /* information extracted during query
724  compilation; speeds up execution:
725  UPD_NODE_NO_ORD_CHANGE and
726  UPD_NODE_NO_SIZE_CHANGE, ORed */
727  /*----------------------*/
728  /* Local storage for this graph node */
729  ulint state; /*!< node execution state */
730  dict_index_t *index; /*!< NULL, or the next index whose record should
731  be updated */
732  dtuple_t *row; /*!< NULL, or a copy (also fields copied to
733  heap) of the row to update; this must be reset
734  to NULL after a successful update */
735  row_ext_t *ext; /*!< NULL, or prefixes of the externally
736  stored columns in the old row */
737  dtuple_t *upd_row; /* NULL, or a copy of the updated row */
738  row_ext_t *upd_ext; /* NULL, or prefixes of the externally
739  stored columns in upd_row */
740  mem_heap_t *heap; /*!< memory heap used as auxiliary storage;
741  this must be emptied after a successful
742  update */
743  /*----------------------*/
744  sym_node_t *table_sym; /* table node in symbol table */
746  /* column assignment list */
747 
748  /** When there is a lock wait error, this remembers current position of
749  the multi-value field, before which the values have been deleted.
750  This will be used for both DELETE and the delete phase of UPDATE. */
752 
753  /** When there is a lock wait error, this remembers current position of
754  the multi-value field, before which the values have been updated. */
756 
757  ulint magic_n;
758 };
759 
760 #define UPD_NODE_MAGIC_N 1579975
761 
762 /* Node execution states */
763 #define UPD_NODE_SET_IX_LOCK \
764  1 /* execution came to the node from \
765  a node above and if the field \
766  has_clust_rec_x_lock is FALSE, we \
767  should set an intention x-lock on \
768  the table */
769 #define UPD_NODE_UPDATE_CLUSTERED \
770  2 /* clustered index record should be \
771  updated */
772 #define UPD_NODE_INSERT_CLUSTERED \
773  3 /* clustered index record should be \
774  inserted, old record is already delete \
775  marked */
776 #define UPD_NODE_UPDATE_ALL_SEC \
777  5 /* an ordering field of the clustered \
778  index record was changed, or this is \
779  a delete operation: should update \
780  all the secondary index records */
781 #define UPD_NODE_UPDATE_SOME_SEC \
782  6 /* secondary index entries should be \
783  looked at and updated if an ordering \
784  field changed */
785 
786 /* Compilation info flags: these must fit within 2 bits; see trx0rec.h */
787 #define UPD_NODE_NO_ORD_CHANGE \
788  1 /* no secondary index record will be \
789  changed in the update and no ordering \
790  field of the clustered index */
791 #define UPD_NODE_NO_SIZE_CHANGE \
792  2 /* no record field size will be \
793  changed in the update */
794 #endif /* !UNIV_HOTBACKUP */
795 
796 #include "row0upd.ic"
797 
798 #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:1679
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:1922
unsigned field_no
field number in an index, usually the clustered index, but in updating a secondary index record in bt...
Definition: row0upd.h:503
std::ostream & print(std::ostream &out) const
Definition: row0upd.cc:3347
Compressed page descriptor.
Definition: page0types.h:197
This structure is used for undo logging of LOB index changes.
Definition: row0upd.h:384
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:751
std::ostream & print(std::ostream &out) const
Definition: row0upd.cc:3331
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:2705
std::vector< Lob_diff, mem_heap_allocator< Lob_diff > > Lob_diff_vector
Definition: row0upd.h:479
ulint n_fields
number of update fields
Definition: row0upd.h:589
bool ext_in_old
If true, the field was stored externally in the old row.
Definition: row0upd.h:523
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:732
dtuple_t * upd_row
Definition: row0upd.h:737
page_no_t lob_first_page_no
The LOB first page number.
Definition: row0upd.h:540
undo_no_t m_modifier_undo_no
Definition: row0upd.h:386
dict_index_t * index
NULL, or the next index whose record should be updated.
Definition: row0upd.h:730
Definition: trx0trx.h:833
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:425
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:1127
mem_heap_t * cascade_heap
NULL or a mem heap where cascade_upd_nodes are created.
Definition: row0upd.h:698
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:536
ulint state
node execution state
Definition: row0upd.h:729
ulint magic_n
Definition: row0upd.h:757
UNIV_INLINE ulint dfield_is_ext(const dfield_t *field)
Determines if a field is externally stored.
Definition: field.h:723
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:2062
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:598
dict_table_t * table
the table object
Definition: row0upd.h:586
Data structure for a database table.
Definition: dict0mem.h:1532
The modification done to the LOB.
Definition: row0upd.h:411
Data structure for a foreign key constraint; an example: FOREIGN KEY (A, B) REFERENCES TABLE2 (C...
Definition: dict0mem.h:1299
dict_table_t * table
table where updated
Definition: row0upd.h:709
row_ext_t * ext
NULL, or prefixes of the externally stored columns in the old row.
Definition: row0upd.h:735
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
Field * mysql_field
the mysql field object.
Definition: row0upd.h:520
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:755
The info structure stored at the beginning of a heap block.
Definition: mem0mem.h:349
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:639
trx_id_t m_modifier_trxid
Definition: row0upd.h:385
Definition: btr0pcur.h:178
SQL data field and tuple.
Definition: table.h:1363
const byte * read_length(const byte *undo_ptr)
Read the length from the undo record.
Definition: row0upd.h:434
dfield_t new_val
new value for the column
Definition: row0upd.h:517
sel_node_t * select
query graph subtree implementing a base table cursor: the rows returned will be updated ...
Definition: row0upd.h:701
SQL parser global types.
Query graph global types.
Definition: row0upd.h:486
void reset()
Reset the update fields.
Definition: row0upd.h:608
que_common_t common
node type: QUE_NODE_UPDATE
Definition: row0upd.h:684
dict_foreign_t * foreign
Definition: row0upd.h:692
std::ostream & print(std::ostream &out) const
Definition: row0upd.h:444
ulint info_bits
new value of info bits to record; default is 0
Definition: row0upd.h:582
mem_heap_t * heap
memory heap used as auxiliary storage; this must be emptied after a successful update ...
Definition: row0upd.h:740
que_node_t * col_assign_list
Definition: row0upd.h:745
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:558
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:438
void set_old_data(const byte *undo_ptr)
Definition: row0upd.h:442
ibool searched_update
Definition: row0upd.h:686
dtuple_t * old_vrow
pointer to old row, used for virtual column update now
Definition: row0upd.h:584
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:670
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:710
dberr_t
Definition: db0err.h:38
Lob_diff(mem_heap_t *mem_heap)
Constructor.
Definition: row0upd.h:415
Row operation global types.
trx_id_t last_trx_id
The last trx that modified the LOB.
Definition: row0upd.h:545
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:1185
Definition: que0que.h:251
que_thr_t * row_upd_step(que_thr_t *thr)
Updates a row in a table.
Definition: row0upd.cc:3230
ulint update_n_fields
Definition: row0upd.h:711
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:685
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:548
Class that represents a single change to a column value in partial update of a JSON column...
Definition: table.h:1280
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:1709
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:689
Transaction system global type definitions.
upd_field_t * fields
array of update fields
Definition: row0upd.h:590
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:822
TABLE * mysql_table
the mysql table object
Definition: row0upd.h:587
A typesafe replacement for DYNAMIC_ARRAY.
Definition: mem_root_array.h:416
bool is_virtual() const
Definition: row0upd.h:501
upd_field_t()
Definition: row0upd.h:487
sym_node_t * table_sym
Definition: row0upd.h:744
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:1729
void que_node_t
Definition: que0types.h:40
mem_heap_t * heap
heap from which memory allocated
Definition: row0upd.h:581
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:360
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:1450
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:583
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:66
A C++ wrapper class to the mem_heap_t routines, so that it can be used as an STL allocator.
Definition: mem0mem.h:398
Lob_index_diff_vec * m_idx_diffs
Changes to the LOB index.
Definition: row0upd.h:473
std::ostream & print(std::ostream &out) const
Print the current object into the given output stream.
Definition: row0upd.h:391
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:704
mem_heap_t * heap
Memory heap in which this object is allocated.
Definition: row0upd.h:560
#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:71
Definition: row0upd.h:683
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:308
bool validate() const
Definition: row0upd.h:615
upd_node_t * cascade_node
Definition: row0upd.h:695
mem_heap_t * heap
Memory heap in which this object is allocated.
Definition: row0upd.h:476
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:3393
row_ext_t * upd_ext
Definition: row0upd.h:738
ibool has_clust_rec_x_lock
Definition: row0upd.h:718
que_node_t * exp
expression for calculating a new value: it refers to column values and constants in the symbol table ...
Definition: row0upd.h:512
dfield_t * old_v_val
old value for the virtual column
Definition: row0upd.h:518
void append(const upd_field_t &field)
Append an update field to the end of array.
Definition: row0upd.h:594
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:516
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:405
unsigned orig_len
original length of the locally stored part of an externally stored column, or 0
Definition: row0upd.h:509
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:1244
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:334
ulint lob_version
Definition: row0upd.h:542
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:533
unsigned char byte
Blob class.
Definition: common.h:159
void reset()
Empty the information collected on LOB diffs.
Definition: row0upd.h:553
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:399
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:747
Definition: completion_hash.h:34
ulint cmpl_info
Definition: row0upd.h:723
#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:1382
void push_lob_diff(const Lob_diff &lob_diff)
Definition: row0upd.h:525
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:803
Dialog Client Authentication nullptr
Definition: dialog.cc:353
Definition: row0upd.h:580
sym_node_list_t columns
Definition: row0upd.h:716
Data structure for an index.
Definition: dict0mem.h:886
Log error(cerr, "ERROR")