1 /*****************************************************************************
2 
3 Copyright (c) 2000, 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/row0mysql.h
28  Interface between Innobase row operations and MySQL.
29  Contains also create table and other data dictionary operations.
30 
31  Created 9/17/2000 Heikki Tuuri
32  *******************************************************/
33 
34 #ifndef row0mysql_h
35 #define row0mysql_h
36 
37 #ifndef UNIV_HOTBACKUP
38 #include "ha_prototypes.h"
39 #endif /* !UNIV_HOTBACKUP */
40 
41 #include <stddef.h>
42 #include <sys/types.h>
43 
44 #include "btr0pcur.h"
45 #include "data0data.h"
46 #include "data0type.h"
47 #include "db0err.h"
48 #include "dict0types.h"
49 #include "fts0fts.h"
50 #include "gis0type.h"
51 #include "lob0undo.h"
52 #include "lock0types.h"
53 #include "mem0mem.h"
54 #include "my_compiler.h"
55 #include "my_inttypes.h"
56 #include "que0types.h"
57 #include "rem0types.h"
58 #include "row0types.h"
59 #include "sess0sess.h"
60 #include "sql_cmd.h"
61 #include "trx0types.h"
62 #include "univ.i"
63 #include "ut0bool_scope_guard.h"
64 
65 // Forward declarations
66 class THD;
67 class ha_innobase;
68 class innodb_session_t;
69 namespace dd {
70 class Table;
71 }
72 struct TABLE;
73 struct btr_pcur_t;
74 struct dfield_t;
75 struct dict_field_t;
76 struct dict_foreign_t;
77 struct dict_index_t;
78 struct dict_table_t;
79 struct dict_v_col_t;
80 struct dtuple_t;
81 struct ins_node_t;
82 struct mtr_t;
83 struct que_fork_t;
84 struct que_thr_t;
85 struct trx_t;
86 struct upd_node_t;
87 struct upd_t;
88 
89 #ifndef UNIV_HOTBACKUP
90 extern ibool row_rollback_on_timeout;
91 
92 struct row_prebuilt_t;
93 
94 /** Frees the blob heap in prebuilt when no longer needed. */
95 void row_mysql_prebuilt_free_blob_heap(
96     row_prebuilt_t *prebuilt); /*!< in: prebuilt struct of a
97                                ha_innobase:: table handle */
98 /** Stores a >= 5.0.3 format true VARCHAR length to dest, in the MySQL row
99  format.
100  @return pointer to the data, we skip the 1 or 2 bytes at the start
101  that are used to store the len */
102 byte *row_mysql_store_true_var_len(
103     byte *dest,    /*!< in: where to store */
104     ulint len,     /*!< in: length, must fit in two bytes */
105     ulint lenlen); /*!< in: storage length of len: either 1 or 2 bytes */
106 /** Reads a >= 5.0.3 format true VARCHAR length, in the MySQL row format, and
107  returns a pointer to the data.
108  @return pointer to the data, we skip the 1 or 2 bytes at the start
109  that are used to store the len */
110 const byte *row_mysql_read_true_varchar(
111     ulint *len,        /*!< out: variable-length field length */
112     const byte *field, /*!< in: field in the MySQL format */
113     ulint lenlen);     /*!< in: storage length of len: either 1
114                        or 2 bytes */
115 /** Stores a reference to a BLOB in the MySQL format. */
116 void row_mysql_store_blob_ref(
117     byte *dest,       /*!< in: where to store */
118     ulint col_len,    /*!< in: dest buffer size: determines into
119                       how many bytes the BLOB length is stored,
120                       the space for the length may vary from 1
121                       to 4 bytes */
122     const void *data, /*!< in: BLOB data; if the value to store
123                       is SQL NULL this should be NULL pointer */
124     ulint len);       /*!< in: BLOB length; if the value to store
125                       is SQL NULL this should be 0; remember
126                       also to set the NULL bit in the MySQL record
127                       header! */
128 /** Reads a reference to a BLOB in the MySQL format.
129 @param[out] len                 BLOB length.
130 @param[in] ref                  BLOB reference in the MySQL format.
131 @param[in] col_len              BLOB reference length (not BLOB length).
132 @return pointer to BLOB data */
133 const byte *row_mysql_read_blob_ref(ulint *len, const byte *ref, ulint col_len);
134 
135 /** Converts InnoDB geometry data format to MySQL data format. */
136 void row_mysql_store_geometry(
137     byte *dest,      /*!< in/out: where to store */
138     ulint dest_len,  /*!< in: dest buffer size: determines into
139                      how many bytes the geometry length is stored,
140                      the space for the length may vary from 1
141                      to 4 bytes */
142     const byte *src, /*!< in: geometry data; if the value to store
143                      is SQL NULL this should be NULL pointer */
144     ulint src_len);  /*!< in: geometry length; if the value to store
145                      is SQL NULL this should be 0; remember
146                      also to set the NULL bit in the MySQL record
147                      header! */
148 /** Pad a column with spaces. */
149 void row_mysql_pad_col(ulint mbminlen, /*!< in: minimum size of a character,
150                                        in bytes */
151                        byte *pad,      /*!< out: padded buffer */
152                        ulint len);     /*!< in: number of bytes to pad */
153 
154 /** Stores a non-SQL-NULL field given in the MySQL format in the InnoDB format.
155  The counterpart of this function is row_sel_field_store_in_mysql_format() in
156  row0sel.cc.
157  @return up to which byte we used buf in the conversion */
158 byte *row_mysql_store_col_in_innobase_format(
159     dfield_t *dfield,       /*!< in/out: dfield where dtype
160                             information must be already set when
161                             this function is called! */
162     byte *buf,              /*!< in/out: buffer for a converted
163                             integer value; this must be at least
164                             col_len long then! NOTE that dfield
165                             may also get a pointer to 'buf',
166                             therefore do not discard this as long
167                             as dfield is used! */
168     ibool row_format_col,   /*!< TRUE if the mysql_data is from
169                             a MySQL row, FALSE if from a MySQL
170                             key value;
171                             in MySQL, a true VARCHAR storage
172                             format differs in a row and in a
173                             key value: in a key value the length
174                             is always stored in 2 bytes! */
175     const byte *mysql_data, /*!< in: MySQL column value, not
176                             SQL NULL; NOTE that dfield may also
177                             get a pointer to mysql_data,
178                             therefore do not discard this as long
179                             as dfield is used! */
180     ulint col_len,          /*!< in: MySQL column length; NOTE that
181                             this is the storage length of the
182                             column in the MySQL format row, not
183                             necessarily the length of the actual
184                             payload data; if the column is a true
185                             VARCHAR then this is irrelevant */
186     ulint comp);            /*!< in: nonzero=compact format */
187 /** Handles user errors and lock waits detected by the database engine.
188  @return true if it was a lock wait and we should continue running the
189  query thread */
190 bool row_mysql_handle_errors(
191     dberr_t *new_err,      /*!< out: possible new error encountered in
192                            rollback, or the old error which was
193                            during the function entry */
194     trx_t *trx,            /*!< in: transaction */
195     que_thr_t *thr,        /*!< in: query thread, or NULL */
196     trx_savept_t *savept); /*!< in: savepoint, or NULL */
197 /** Create a prebuilt struct for a MySQL table handle.
198  @return own: a prebuilt struct */
199 row_prebuilt_t *row_create_prebuilt(
200     dict_table_t *table,  /*!< in: Innobase table handle */
201     ulint mysql_row_len); /*!< in: length in bytes of a row in
202                           the MySQL format */
203 /** Free a prebuilt struct for a MySQL table handle. */
204 void row_prebuilt_free(
205     row_prebuilt_t *prebuilt, /*!< in, own: prebuilt struct */
206     ibool dict_locked);       /*!< in: TRUE=data dictionary locked */
207 
208 /** Updates the transaction pointers in query graphs stored in the prebuilt
209 struct.
210 @param[in,out] prebuilt         Prebuilt struct in MySQL handle.
211 @param[in,out] trx              Transaction handle. */
212 void row_update_prebuilt_trx(row_prebuilt_t *prebuilt, trx_t *trx);
213 
214 /** Sets an AUTO_INC type lock on the table mentioned in prebuilt. The
215  AUTO_INC lock gives exclusive access to the auto-inc counter of the
216  table. The lock is reserved only for the duration of an SQL statement.
217  It is not compatible with another AUTO_INC or exclusive lock on the
218  table.
219  @return error code or DB_SUCCESS */
220 dberr_t row_lock_table_autoinc_for_mysql(
221     row_prebuilt_t *prebuilt) /*!< in: prebuilt struct in the MySQL
222                               table handle */
223     MY_ATTRIBUTE((warn_unused_result));
224 /** Sets a table lock on the table mentioned in prebuilt.
225 @param[in,out]	prebuilt	table handle
226 @return error code or DB_SUCCESS */
227 dberr_t row_lock_table(row_prebuilt_t *prebuilt);
228 
229 /** Does an insert for MySQL.
230 @param[in]	mysql_rec	row in the MySQL format
231 @param[in,out]	prebuilt	prebuilt struct in MySQL handle
232 @return error code or DB_SUCCESS*/
233 dberr_t row_insert_for_mysql(const byte *mysql_rec, row_prebuilt_t *prebuilt)
234     MY_ATTRIBUTE((warn_unused_result));
235 
236 /** Builds a dummy query graph used in selects. */
237 void row_prebuild_sel_graph(row_prebuilt_t *prebuilt); /*!< in: prebuilt struct
238                                                        in MySQL handle */
239 /** Gets pointer to a prebuilt update vector used in updates. If the update
240  graph has not yet been built in the prebuilt struct, then this function
241  first builds it.
242  @return prebuilt update vector */
243 upd_t *row_get_prebuilt_update_vector(
244     row_prebuilt_t *prebuilt); /*!< in: prebuilt struct in MySQL
245                                handle */
246 /** Checks if a table is such that we automatically created a clustered
247  index on it (on row id).
248  @return true if the clustered index was generated automatically */
249 ibool row_table_got_default_clust_index(
250     const dict_table_t *table); /*!< in: table */
251 
252 /** Does an update or delete of a row for MySQL.
253 @param[in]	mysql_rec	row in the MySQL format
254 @param[in,out]	prebuilt	prebuilt struct in MySQL handle
255 @return error code or DB_SUCCESS */
256 dberr_t row_update_for_mysql(const byte *mysql_rec, row_prebuilt_t *prebuilt)
257     MY_ATTRIBUTE((warn_unused_result));
258 
259 /** Delete all rows for the given table by freeing/truncating indexes.
260 @param[in,out]	table	table handler */
261 void row_delete_all_rows(dict_table_t *table);
262 
263 /** This can only be used when this session is using a READ COMMITTED or READ
264 UNCOMMITTED isolation level.  Before calling this function
265 row_search_for_mysql() must have initialized prebuilt->new_rec_locks to store
266 the information which new record locks really were set. This function removes
267 a newly set clustered index record lock under prebuilt->pcur or
268 prebuilt->clust_pcur.  Thus, this implements a 'mini-rollback' that releases
269 the latest clustered index record lock we set.
270 
271 @param[in,out]	prebuilt		prebuilt struct in MySQL handle
272 @param[in]	has_latches_on_recs	TRUE if called so that we have the
273                                         latches on the records under pcur
274                                         and clust_pcur, and we do not need
275                                         to reposition the cursors. */
276 void row_unlock_for_mysql(row_prebuilt_t *prebuilt, ibool has_latches_on_recs);
277 #endif /* !UNIV_HOTBACKUP */
278 
279 /** Checks if a table name contains the string "/#sql" which denotes temporary
280  tables in MySQL.
281  @return true if temporary table */
282 bool row_is_mysql_tmp_table_name(const char *name)
283     MY_ATTRIBUTE((warn_unused_result));
284 /*!< in: table name in the form
285 'database/tablename' */
286 
287 #ifndef UNIV_HOTBACKUP
288 /** Creates an query graph node of 'update' type to be used in the MySQL
289  interface.
290  @return own: update node */
291 upd_node_t *row_create_update_node_for_mysql(
292     dict_table_t *table, /*!< in: table to update */
293     mem_heap_t *heap);   /*!< in: mem heap from which allocated */
294 /** Does a cascaded delete or set null in a foreign key operation.
295  @return error code or DB_SUCCESS */
296 dberr_t row_update_cascade_for_mysql(
297     que_thr_t *thr,      /*!< in: query thread */
298     upd_node_t *node,    /*!< in: update node used in the cascade
299                          or set null operation */
300     dict_table_t *table) /*!< in: table where we do the operation */
301     MY_ATTRIBUTE((nonnull, warn_unused_result));
302 /** Locks the data dictionary exclusively for performing a table create or other
303  data dictionary modification operation. */
304 void row_mysql_lock_data_dictionary_func(trx_t *trx, /*!< in/out: transaction */
305                                          const char *file, /*!< in: file name */
306                                          ulint line); /*!< in: line number */
307 #define row_mysql_lock_data_dictionary(trx) \
308   row_mysql_lock_data_dictionary_func(trx, __FILE__, __LINE__)
309 /** Unlocks the data dictionary exclusive lock. */
310 void row_mysql_unlock_data_dictionary(trx_t *trx); /*!< in/out: transaction */
311 /** Locks the data dictionary in shared mode from modifications, for performing
312  foreign key check, rollback, or other operation invisible to MySQL. */
313 void row_mysql_freeze_data_dictionary_func(
314     trx_t *trx,       /*!< in/out: transaction */
315     const char *file, /*!< in: file name */
316     ulint line);      /*!< in: line number */
317 #define row_mysql_freeze_data_dictionary(trx) \
318   row_mysql_freeze_data_dictionary_func(trx, __FILE__, __LINE__)
319 /** Unlocks the data dictionary shared lock. */
320 void row_mysql_unfreeze_data_dictionary(trx_t *trx); /*!< in/out: transaction */
321 /** Creates a table for MySQL. On success the in-memory table could be
322 kept in non-LRU list while on failure the 'table' object will be freed.
323 @param[in]	table		table definition(will be freed, or on
324                                 DB_SUCCESS added to the data dictionary cache)
325 @param[in]	compression	compression algorithm to use, can be nullptr
326 @param[in,out]	trx		transasction
327 @return error code or DB_SUCCESS */
328 dberr_t row_create_table_for_mysql(dict_table_t *table, const char *compression,
329                                    trx_t *trx)
330     MY_ATTRIBUTE((warn_unused_result));
331 /** Does an index creation operation for MySQL. TODO: currently failure
332  to create an index results in dropping the whole table! This is no problem
333  currently as all indexes must be created at the same time as the table.
334  @return error number or DB_SUCCESS */
335 dberr_t row_create_index_for_mysql(
336     dict_index_t *index,        /*!< in, own: index definition
337                                 (will be freed) */
338     trx_t *trx,                 /*!< in: transaction handle */
339     const ulint *field_lengths, /*!< in: if not NULL, must contain
340                                 dict_index_get_n_fields(index)
341                                 actual field lengths for the
342                                 index columns, which are
343                                 then checked for not being too
344                                 large. */
345     dict_table_t *handler)      /* ! in/out: table handler. */
346     MY_ATTRIBUTE((warn_unused_result));
347 
348 /** Loads foreign key constraints for the table being created. This
349  function should be called after the indexes for a table have been
350  created. Each foreign key constraint must be accompanied with indexes
351  in both participating tables. The indexes are allowed to contain more
352  fields than mentioned in the constraint.
353 
354  @param[in]	trx		transaction
355  @param[in]	name		table full name in normalized form
356  @param[in]	dd_table	MySQL dd::Table for the table
357  @return error code or DB_SUCCESS */
358 dberr_t row_table_load_foreign_constraints(trx_t *trx, const char *name,
359                                            const dd::Table *dd_table)
360     MY_ATTRIBUTE((warn_unused_result));
361 
362 /** The master thread in srv0srv.cc calls this regularly to drop tables which
363  we must drop in background after queries to them have ended. Such lazy
364  dropping of tables is needed in ALTER TABLE on Unix.
365  @return how many tables dropped + remaining tables in list */
366 ulint row_drop_tables_for_mysql_in_background(void);
367 /** Get the background drop list length. NOTE: the caller must own the kernel
368  mutex!
369  @return how many tables in list */
370 ulint row_get_background_drop_list_len_low(void);
371 
372 /** Sets an exclusive lock on a table.
373  @return error code or DB_SUCCESS */
374 dberr_t row_mysql_lock_table(
375     trx_t *trx,          /*!< in/out: transaction */
376     dict_table_t *table, /*!< in: table to lock */
377     enum lock_mode mode, /*!< in: LOCK_X or LOCK_S */
378     const char *op_info) /*!< in: string for trx->op_info */
379     MY_ATTRIBUTE((warn_unused_result));
380 
381 /** Drop a tablespace as part of dropping or renaming a table.
382 This deletes the fil_space_t if found and the file on disk.
383 @param[in]	space_id	Tablespace ID
384 @param[in]	filepath	File path of tablespace to delete
385 @return error code or DB_SUCCESS */
386 dberr_t row_drop_tablespace(space_id_t space_id, const char *filepath);
387 
388 /** Drop a table for MySQL. If the data dictionary was not already locked
389 by the transaction, the transaction will be committed.  Otherwise, the
390 data dictionary will remain locked.
391 @param[in]	name		table name
392 @param[in,out]	trx		data dictionary transaction
393 @param[in]	nonatomic	whether it is permitted
394 to release and reacquire dict_operation_lock
395 @param[in,out]	handler		intrinsic temporary table handle, or NULL
396 @return error code or DB_SUCCESS */
397 dberr_t row_drop_table_for_mysql(const char *name, trx_t *trx, bool nonatomic,
398                                  dict_table_t *handler = nullptr);
399 /** Drop a table for MySQL. If the data dictionary was not already locked
400 by the transaction, the transaction will be committed.  Otherwise, the
401 data dictionary will remain locked.
402 @param[in]	name		table name
403 @param[in,out]	trx		data dictionary transaction
404 @return error code or DB_SUCCESS */
row_drop_table_for_mysql(const char * name,trx_t * trx)405 inline dberr_t row_drop_table_for_mysql(const char *name, trx_t *trx) {
406   return (row_drop_table_for_mysql(name, trx, true, nullptr));
407 }
408 
409 /** Discards the tablespace of a table which stored in an .ibd file. Discarding
410  means that this function deletes the .ibd file and assigns a new table id for
411  the table. Also the flag table->ibd_file_missing is set TRUE.
412  @return error code or DB_SUCCESS */
413 dberr_t row_discard_tablespace_for_mysql(
414     const char *name, /*!< in: table name */
415     trx_t *trx)       /*!< in: transaction handle */
416     MY_ATTRIBUTE((warn_unused_result));
417 /** Imports a tablespace. The space id in the .ibd file must match the space id
418  of the table in the data dictionary.
419  @return error code or DB_SUCCESS */
420 dberr_t row_import_tablespace_for_mysql(
421     dict_table_t *table,      /*!< in/out: table */
422     row_prebuilt_t *prebuilt) /*!< in: prebuilt struct in MySQL */
423     MY_ATTRIBUTE((warn_unused_result));
424 
425 /** Drop a database for MySQL.
426 @param[in]	name	database name which ends at '/'
427 @param[in]	trx	transaction handle
428 @param[out]	found	number of dropped tables
429 @return error code or DB_SUCCESS */
430 dberr_t row_drop_database_for_mysql(const char *name, trx_t *trx, ulint *found);
431 
432 /** Renames a table for MySQL.
433 @param[in]	old_name	old table name
434 @param[in]	new_name	new table name
435 @param[in]	dd_table	dd::Table for new table
436 @param[in,out]	trx		transaction
437 @param[in]      replay          whether in replay stage
438 @return error code or DB_SUCCESS */
439 dberr_t row_rename_table_for_mysql(const char *old_name, const char *new_name,
440                                    const dd::Table *dd_table, trx_t *trx,
441                                    bool replay)
442     MY_ATTRIBUTE((warn_unused_result));
443 
444 /** Read the total number of records in a consistent view.
445 @param[in,out]  trx             Covering transaction.
446 @param[in]  indexes             Indexes to scan.
447 @param[in]  max_threads         Maximum number of threads to use.
448 @param[out] n_rows              Number of rows seen.
449 @return DB_SUCCESS or error code. */
450 dberr_t row_mysql_parallel_select_count_star(
451     trx_t *trx, std::vector<dict_index_t *> &indexes, size_t max_threads,
452     ulint *n_rows);
453 
454 /** Scans an index for either COUNT(*) or CHECK TABLE.
455 If CHECK TABLE; Checks that the index contains entries in an ascending order,
456 unique constraint is not broken, and calculates the number of index entries
457 in the read view of the current transaction.
458 @param[in,out]  prebuilt    Prebuilt struct in MySQL handle.
459 @param[in,out]  index       Index to scan.
460 @param[in]      n_threads   Number of threads to use for the scan
461 @param[in]      check_keys  True if called form check table.
462 @param[out]     n_rows      Number of entries seen in the consistent read.
463 @return DB_SUCCESS or other error */
464 dberr_t row_scan_index_for_mysql(row_prebuilt_t *prebuilt, dict_index_t *index,
465                                  size_t n_threads, bool check_keys,
466                                  ulint *n_rows)
467     MY_ATTRIBUTE((warn_unused_result));
468 /** Initialize this module */
469 void row_mysql_init(void);
470 
471 /** Close this module */
472 void row_mysql_close(void);
473 
474 /* A struct describing a place for an individual column in the MySQL
475 row format which is presented to the table handler in ha_innobase.
476 This template struct is used to speed up row transformations between
477 Innobase and MySQL. */
478 
479 struct mysql_row_templ_t {
480   ulint col_no;                 /*!< column number of the column */
481   ulint rec_field_no;           /*!< field number of the column in an
482                                 Innobase record in the current index;
483                                 not defined if template_type is
484                                 ROW_MYSQL_WHOLE_ROW */
485   ulint clust_rec_field_no;     /*!< field number of the column in an
486                                 Innobase record in the clustered index;
487                                 not defined if template_type is
488                                 ROW_MYSQL_WHOLE_ROW */
489   ulint icp_rec_field_no;       /*!< field number of the column in an
490                                 Innobase record in the current index;
491                                 only defined for columns that could be
492                                 used to evaluate a pushed down index
493                                 condition and/or end-range condition */
494   ulint mysql_col_offset;       /*!< offset of the column in the MySQL
495                                 row format */
496   ulint mysql_col_len;          /*!< length of the column in the MySQL
497                                 row format */
498   ulint mysql_mvidx_len;        /*!< index length on multi-value array */
499   ulint mysql_null_byte_offset; /*!< MySQL NULL bit byte offset in a
500                                 MySQL record */
501   ulint mysql_null_bit_mask;    /*!< bit mask to get the NULL bit,
502                                 zero if column cannot be NULL */
503   ulint type;                   /*!< column type in Innobase mtype
504                                 numbers DATA_CHAR... */
505   ulint mysql_type;             /*!< MySQL type code; this is always
506                                 < 256 */
507   ulint mysql_length_bytes;     /*!< if mysql_type
508                                 == DATA_MYSQL_TRUE_VARCHAR, this tells
509                                 whether we should use 1 or 2 bytes to
510                                 store the MySQL true VARCHAR data
511                                 length at the start of row in the MySQL
512                                 format (NOTE that the MySQL key value
513                                 format always uses 2 bytes for the data
514                                 len) */
515   ulint charset;                /*!< MySQL charset-collation code
516                                 of the column, or zero */
517   ulint mbminlen;               /*!< minimum length of a char, in bytes,
518                                 or zero if not a char type */
519   ulint mbmaxlen;               /*!< maximum length of a char, in bytes,
520                                 or zero if not a char type */
521   ulint is_unsigned;            /*!< if a column type is an integer
522                                 type and this field is != 0, then
523                                 it is an unsigned integer type */
524   ulint is_virtual;             /*!< if a column is a virtual column */
525   ulint is_multi_val;           /*!< if a column is a Multi-Value Array virtual
526                                 column */
527 };
528 
529 #define MYSQL_FETCH_CACHE_SIZE 8
530 /* After fetching this many rows, we start caching them in fetch_cache */
531 #define MYSQL_FETCH_CACHE_THRESHOLD 4
532 
533 #define ROW_PREBUILT_ALLOCATED 78540783
534 #define ROW_PREBUILT_FREED 26423527
535 
536 /** A struct for (sometimes lazily) prebuilt structures in an Innobase table
537 handle used within MySQL; these are used to save CPU time. */
538 
539 struct row_prebuilt_t {
540   ulint magic_n;               /*!< this magic number is set to
541                                ROW_PREBUILT_ALLOCATED when created,
542                                or ROW_PREBUILT_FREED when the
543                                struct has been freed */
544   dict_table_t *table;         /*!< Innobase table handle */
545   dict_index_t *index;         /*!< current index for a search, if
546                                any */
547   trx_t *trx;                  /*!< current transaction handle */
548   unsigned sql_stat_start : 1; /*!< TRUE when we start processing of
549                               an SQL statement: we may have to set
550                               an intention lock on the table,
551                               create a consistent read view etc. */
552   unsigned clust_index_was_generated : 1;
553   /*!< if the user did not define a
554   primary key in MySQL, then Innobase
555   automatically generated a clustered
556   index where the ordering column is
557   the row id: in this case this flag
558   is set to TRUE */
559   unsigned index_usable : 1;               /*!< caches the value of
560                                            index->is_usable(trx) */
561   unsigned read_just_key : 1;              /*!< set to 1 when MySQL calls
562                                            ha_innobase::extra with the
563                                            argument HA_EXTRA_KEYREAD; it is enough
564                                            to read just columns defined in
565                                            the index (i.e., no read of the
566                                            clustered index record necessary) */
567   unsigned used_in_HANDLER : 1;            /*!< TRUE if we have been using this
568                                          handle in a MySQL HANDLER low level
569                                          index cursor command: then we must
570                                          store the pcur position even in a
571                                          unique search from a clustered index,
572                                          because HANDLER allows NEXT and PREV
573                                          in such a situation */
574   unsigned template_type : 2;              /*!< ROW_MYSQL_WHOLE_ROW,
575                                            ROW_MYSQL_REC_FIELDS,
576                                            ROW_MYSQL_DUMMY_TEMPLATE, or
577                                            ROW_MYSQL_NO_TEMPLATE */
578   unsigned n_template : 10;                /*!< number of elements in the
579                                            template */
580   unsigned null_bitmap_len : 10;           /*!< number of bytes in the SQL NULL
581                                         bitmap at the start of a row in the
582                                         MySQL format */
583   unsigned need_to_access_clustered : 1;   /*!< if we are fetching
584                                columns through a secondary index
585                                and at least one column is not in
586                                the secondary index, then this is
587                                set to TRUE */
588   unsigned templ_contains_blob : 1;        /*!< TRUE if the template contains
589                                      a column with DATA_LARGE_MTYPE(
590                                      get_innobase_type_from_mysql_type())
591                                      is TRUE;
592                                      not to be confused with InnoDB
593                                      externally stored columns
594                                      (VARCHAR can be off-page too) */
595   unsigned templ_contains_fixed_point : 1; /*!< TRUE if the
596                               template contains a column with
597                               DATA_POINT. Since InnoDB regards
598                               DATA_POINT as non-BLOB type, the
599                               templ_contains_blob can't tell us
600                               if there is DATA_POINT */
601 
602   /** 1 if extra(HA_EXTRA_INSERT_WITH_UPDATE) was requested, which happens
603   when ON DUPLICATE KEY UPDATE clause is present, 0 otherwise */
604   unsigned on_duplicate_key_update : 1;
605 
606   /** 1 if extra(HA_EXTRA_WRITE_CAN_REPLACE) was requested, which happen when
607   REPLACE is done instead of regular INSERT, 0 otherwise */
608   unsigned replace : 1;
609 
610   /** template used to transform rows fast between MySQL and Innobase formats;
611   memory for this template is not allocated from 'heap' */
612   mysql_row_templ_t *mysql_template;
613 
614   /** memory heap from which these auxiliary structures are allocated when
615   needed */
616   mem_heap_t *heap;
617 
618   /** memory heap from which innodb_api_buf is allocated per session */
619   mem_heap_t *cursor_heap;
620 
621   /** Innobase SQL insert node used to perform inserts to the table */
622   ins_node_t *ins_node;
623 
624   /** buffer for storing data converted to the Innobase format from the MySQL
625   format */
626   byte *ins_upd_rec_buff;
627 
628   /* buffer for converting data format for multi-value virtual columns */
629   multi_value_data *mv_data;
630   const byte *default_rec; /*!< the default values of all columns
631                            (a "default row") in MySQL format */
632   ulint hint_need_to_fetch_extra_cols;
633   /*!< normally this is set to 0; if this
634   is set to ROW_RETRIEVE_PRIMARY_KEY,
635   then we should at least retrieve all
636   columns in the primary key; if this
637   is set to ROW_RETRIEVE_ALL_COLS, then
638   we must retrieve all columns in the
639   key (if read_just_key == 1), or all
640   columns in the table */
641   upd_node_t *upd_node;   /*!< Innobase SQL update node used
642                           to perform updates and deletes */
643   trx_id_t trx_id;        /*!< The table->def_trx_id when
644                           ins_graph was built */
645   que_fork_t *ins_graph;  /*!< Innobase SQL query graph used
646                           in inserts. Will be rebuilt on
647                           trx_id or n_indexes mismatch. */
648   que_fork_t *upd_graph;  /*!< Innobase SQL query graph used
649                           in updates or deletes */
650   btr_pcur_t *pcur;       /*!< persistent cursor used in selects
651                           and updates */
652   btr_pcur_t *clust_pcur; /*!< persistent cursor used in
653                           some selects and updates */
654   que_fork_t *sel_graph;  /*!< dummy query graph used in
655                           selects */
656   dtuple_t *search_tuple; /*!< prebuilt dtuple used in selects */
657 
658   /** prebuilt dtuple used in selects where the end of range is known */
659   dtuple_t *m_stop_tuple;
660 
661   /** Set to true in row_search_mvcc when a row matching exactly the length and
662   value of stop_tuple was found, so that the next iteration of row_search_mvcc
663   knows it can simply return DB_RECORD_NOT_FOUND. If true, then for sure, at
664   least one such matching row was seen. If false, it might be false negative, as
665   not all control paths lead to setting this field to true in case a matching
666   row is visited. */
667   bool m_stop_tuple_found;
668 
669  private:
670   /** Set to true iff we are inside read_range_first() or read_range_next() */
671   bool m_is_reading_range;
672 
673  public:
is_reading_rangerow_prebuilt_t674   bool is_reading_range() const { return m_is_reading_range; }
675 
676   class row_is_reading_range_guard_t : private ut::bool_scope_guard_t {
677    public:
row_is_reading_range_guard_trow_prebuilt_t678     explicit row_is_reading_range_guard_t(row_prebuilt_t &prebuilt)
679         : ut::bool_scope_guard_t(prebuilt.m_is_reading_range) {}
680   };
681 
get_is_reading_range_guardrow_prebuilt_t682   row_is_reading_range_guard_t get_is_reading_range_guard() {
683     /* We implement row_is_reading_range_guard_t as a simple bool_scope_guard_t
684     because we trust that scopes are never nested and thus we don't need to
685     count their "openings" and "closings", so we assert that.*/
686     ut_ad(!m_is_reading_range);
687     return row_is_reading_range_guard_t(*this);
688   }
689 
690   byte row_id[DATA_ROW_ID_LEN];
691   /*!< if the clustered index was
692   generated, the row id of the
693   last row fetched is stored
694   here */
695   doc_id_t fts_doc_id;          /* if the table has an FTS index on
696                                 it then we fetch the doc_id.
697                                 FTS-FIXME: Currently we fetch it always
698                                 but in the future we must only fetch
699                                 it when FTS columns are being
700                                 updated */
701   dtuple_t *clust_ref;          /*!< prebuilt dtuple used in
702                                 sel/upd/del */
703   ulint select_lock_type;       /*!< LOCK_NONE, LOCK_S, or LOCK_X */
704   enum select_mode select_mode; /*!< SELECT_ORDINARY,
705                                 SELECT_SKIP_LOKCED, or SELECT_NO_WAIT */
706   ulint row_read_type;          /*!< ROW_READ_WITH_LOCKS if row locks
707                                 should be the obtained for records
708                                 under an UPDATE or DELETE cursor.
709                                 If trx_t::allow_semi_consistent()
710                                 returns true, this can be set to
711                                 ROW_READ_TRY_SEMI_CONSISTENT, so that
712                                 if the row under an UPDATE or DELETE
713                                 cursor was locked by another
714                                 transaction, InnoDB will resort
715                                 to reading the last committed value
716                                 ('semi-consistent read').  Then,
717                                 this field will be set to
718                                 ROW_READ_DID_SEMI_CONSISTENT to
719                                 indicate that.	If the row does not
720                                 match the WHERE condition, MySQL will
721                                 invoke handler::unlock_row() to
722                                 clear the flag back to
723                                 ROW_READ_TRY_SEMI_CONSISTENT and
724                                 to simply skip the row.	 If
725                                 the row matches, the next call to
726                                 row_search_for_mysql() will lock
727                                 the row.
728                                 This eliminates lock waits in some
729                                 cases; note that this breaks
730                                 serializability. */
731 
732   enum {
733     LOCK_PCUR,
734     LOCK_CLUST_PCUR,
735     LOCK_COUNT,
736   };
737 
738   bool new_rec_lock[LOCK_COUNT]; /*!< normally false; if
739                         session is using READ COMMITTED or READ UNCOMMITTED
740                         isolation level, set in row_search_for_mysql() if we set
741                         a new record lock on the secondary or clustered index;
742                         this is used in row_unlock_for_mysql() when releasing
743                         the lock under the cursor if we determine after
744                         retrieving the row that it does not need to be locked
745                         ('mini-rollback')
746                         [LOCK_PCUR] corresponds to pcur, the first index we
747                         looked up (can be secondary or clustered!)
748 
749                         [LOCK_CLUST_PCUR] corresponds to clust_pcur, which if
750                         used at all, is always the clustered index.
751 
752                         The meaning of these booleans is:
753                         true = we've created a rec lock, which we might
754                                release as we "own" it
755                         false = we should not release any lock for this
756                                index as we either reused some existing
757                                lock, or there is some other reason, we
758                                should keep it
759                         */
760   ulint mysql_prefix_len;        /*!< byte offset of the end of
761                                  the last requested column */
762   ulint mysql_row_len;           /*!< length in bytes of a row in the
763                                  MySQL format */
764   ulint n_rows_fetched;          /*!< number of rows fetched after
765                                  positioning the current cursor */
766   ulint fetch_direction;         /*!< ROW_SEL_NEXT or ROW_SEL_PREV */
767 
768   byte *fetch_cache[MYSQL_FETCH_CACHE_SIZE];
769   /*!< a cache for fetched rows if we
770   fetch many rows from the same cursor:
771   it saves CPU time to fetch them in a
772   batch; we reserve mysql_row_len
773   bytes for each such row; these
774   pointers point 4 bytes past the
775   allocated mem buf start, because
776   there is a 4 byte magic number at the
777   start and at the end */
778   ibool keep_other_fields_on_keyread; /*!< when using fetch
779                         cache with HA_EXTRA_KEYREAD, don't
780                         overwrite other fields in mysql row
781                         row buffer.*/
782   ulint fetch_cache_first;            /*!< position of the first not yet
783                                     fetched row in fetch_cache */
784   ulint n_fetch_cached;               /*!< number of not yet fetched rows
785                                       in fetch_cache */
786   mem_heap_t *blob_heap;              /*!< in SELECTS BLOB fields are copied
787                                       to this heap */
788   mem_heap_t *old_vers_heap;          /*!< memory heap where a previous
789                                       version is built in consistent read */
790   bool in_fts_query;                  /*!< Whether we are in a FTS query */
791   bool fts_doc_id_in_read_set;        /*!< true if table has externally
792                               defined FTS_DOC_ID coulmn. */
793   /*----------------------*/
794   ulonglong autoinc_last_value;
795   /*!< last value of AUTO-INC interval */
796   ulonglong autoinc_increment; /*!< The increment step of the auto
797                              increment column. Value must be
798                              greater than or equal to 1. Required to
799                              calculate the next value */
800   ulonglong autoinc_offset;    /*!< The offset passed to
801                                get_auto_increment() by MySQL. Required
802                                to calculate the next value */
803   dberr_t autoinc_error;       /*!< The actual error code encountered
804                                while trying to init or read the
805                                autoinc value from the table. We
806                                store it here so that we can return
807                                it to MySQL */
808   /*----------------------*/
809   bool idx_cond;         /*!< True if index condition pushdown
810                          is used, false otherwise. */
811   ulint idx_cond_n_cols; /*!< Number of fields in idx_cond_cols.
812                          0 if and only if idx_cond == false. */
813   /*----------------------*/
814   unsigned innodb_api : 1;     /*!< whether this is a InnoDB API
815                                query */
816   const rec_t *innodb_api_rec; /*!< InnoDB API search result */
817   void *innodb_api_buf;        /*!< Buffer holding copy of the physical
818                                Innodb API search record */
819   ulint innodb_api_rec_size;   /*!< Size of the Innodb API record */
820   /*----------------------*/
821 
822   /*----------------------*/
823   rtr_info_t *rtr_info; /*!< R-tree Search Info */
824   /*----------------------*/
825 
826   ulint magic_n2; /*!< this should be the same as
827                   magic_n */
828 
829   bool ins_sel_stmt; /*!< if true then ins_sel_statement. */
830 
831   innodb_session_t *session; /*!< InnoDB session handler. */
832   byte *srch_key_val1;       /*!< buffer used in converting
833                              search key values from MySQL format
834                              to InnoDB format.*/
835   byte *srch_key_val2;       /*!< buffer used in converting
836                              search key values from MySQL format
837                              to InnoDB format.*/
838   uint srch_key_val_len;     /*!< Size of search key */
839   /** Disable prefetch. */
840   bool m_no_prefetch;
841 
842   bool skip_serializable_dd_view;
843   /* true, if we want skip serializable
844   isolation level on views on DD tables */
845   bool no_autoinc_locking;
846   /* true, if we were asked to skip
847   AUTOINC locking for the table. */
848   /** Return materialized key for secondary index scan */
849   bool m_read_virtual_key;
850 
851   /** Whether this is a temporary(intrinsic) table read to keep the position
852   for this MySQL TABLE object */
853   bool m_temp_read_shared;
854 
855   /** Whether tree modifying operation happened on a temporary (intrinsic)
856   table index tree. In this case, it could be split, but no shrink. */
857   bool m_temp_tree_modified;
858 
859   /** The MySQL table object */
860   TABLE *m_mysql_table;
861 
862   /** The MySQL handler object. */
863   ha_innobase *m_mysql_handler;
864 
865   /** limit value to avoid fts result overflow */
866   ulonglong m_fts_limit;
867 
868   /** True if exceeded the end_range while filling the prefetch cache. */
869   bool m_end_range;
870 
871   /** Undo information for LOB mvcc */
872   lob::undo_vers_t m_lob_undo;
873 
get_lob_undorow_prebuilt_t874   lob::undo_vers_t *get_lob_undo() { return (&m_lob_undo); }
875 
lob_undo_resetrow_prebuilt_t876   void lob_undo_reset() { m_lob_undo.reset(); }
877 
878   /** Can a record buffer or a prefetch cache be utilized for prefetching
879   records in this scan?
880   @retval true   if records can be prefetched
881   @retval false  if records cannot be prefetched */
882   bool can_prefetch_records() const;
883 
884   /** Determines if the query is REPLACE or ON DUPLICATE KEY UPDATE in which
885   case duplicate values should be allowed (and further processed) instead of
886   causing an error.
887   @return true iff duplicated values should be allowed */
allow_duplicatesrow_prebuilt_t888   bool allow_duplicates() { return (replace || on_duplicate_key_update); }
889 
890  private:
891   /** A helper function for init_search_tuples_types() which prepares the shape
892   of the tuple to match the index
893   @param[in]  tuple   this->search_tuple or this->m_stop_tuple */
init_tuple_typesrow_prebuilt_t894   void init_tuple_types(dtuple_t *tuple) {
895     dtuple_set_n_fields(tuple, index->n_fields);
896     dict_index_copy_types(tuple, index, index->n_fields);
897   }
898 
899  public:
900   /** Initializes search_tuple and m_stop_tuple shape so they match the index */
init_search_tuples_typesrow_prebuilt_t901   void init_search_tuples_types() {
902     init_tuple_types(search_tuple);
903     init_tuple_types(m_stop_tuple);
904   }
905 
906   /** Resets both search_tuple and m_stop_tuple */
clear_search_tuplesrow_prebuilt_t907   void clear_search_tuples() {
908     dtuple_set_n_fields(search_tuple, 0);
909     dtuple_set_n_fields(m_stop_tuple, 0);
910   }
911 
912   /** @return true iff the operation can skip concurrency ticket. */
913   bool skip_concurrency_ticket() const;
914 
915   /** It is unsafe to copy this struct, and moving it would be non-trivial,
916   because we want to keep in sync with row_is_reading_range_guard_t. Therefore
917   it is much safer/easier to just forbid such operations.  */
918   row_prebuilt_t(row_prebuilt_t const &) = delete;
919   row_prebuilt_t &operator=(row_prebuilt_t const &) = delete;
920   row_prebuilt_t &operator=(row_prebuilt_t &&) = delete;
921   row_prebuilt_t(row_prebuilt_t &&) = delete;
922 };
923 
924 /** Callback for row_mysql_sys_index_iterate() */
925 struct SysIndexCallback {
~SysIndexCallbackSysIndexCallback926   virtual ~SysIndexCallback() {}
927 
928   /** Callback method
929   @param mtr current mini transaction
930   @param pcur persistent cursor. */
931   virtual void operator()(mtr_t *mtr, btr_pcur_t *pcur) noexcept = 0;
932 };
933 
934 /** Get the computed value by supplying the base column values.
935 @param[in,out]	row		the data row
936 @param[in]	col		virtual column
937 @param[in]	index		index on the virtual column
938 @param[in,out]	local_heap	heap memory for processing large data etc.
939 @param[in,out]	heap		memory heap that copies the actual index row
940 @param[in]	ifield		index field
941 @param[in]	thd		MySQL thread handle
942 @param[in,out]	mysql_table	mysql table object
943 @param[in]	old_table	during ALTER TABLE, this is the old table
944                                 or NULL.
945 @param[in]	parent_update	update vector for the parent row
946 @param[in]	foreign		foreign key information
947 @return the field filled with computed value */
948 dfield_t *innobase_get_computed_value(
949     const dtuple_t *row, const dict_v_col_t *col, const dict_index_t *index,
950     mem_heap_t **local_heap, mem_heap_t *heap, const dict_field_t *ifield,
951     THD *thd, TABLE *mysql_table, const dict_table_t *old_table,
952     upd_t *parent_update, dict_foreign_t *foreign);
953 
954 /** Parse out multi-values from a MySQL record
955 @param[in]      mysql_table     MySQL table structure
956 @param[in]      f_idx           field index of the multi-value column
957 @param[in,out]  dfield          field structure to store parsed multi-value
958 @param[in,out]  value           nullptr or the multi-value structure
959                                 to store the parsed values
960 @param[in]      old_val         old value if exists
961 @param[in]      comp            true if InnoDB table uses compact row format
962 @param[in,out]  heap            memory heap */
963 void innobase_get_multi_value(const TABLE *mysql_table, ulint f_idx,
964                               dfield_t *dfield, multi_value_data *value,
965                               uint old_val, ulint comp, mem_heap_t *heap);
966 
967 /** Get the computed value by supplying the base column values.
968 @param[in,out]	table	the table whose virtual column template to be built */
969 void innobase_init_vc_templ(dict_table_t *table);
970 
971 /** Change dbname and table name in table->vc_templ.
972 @param[in,out]	table	the table whose virtual column template
973 dbname and tbname to be renamed. */
974 void innobase_rename_vc_templ(dict_table_t *table);
975 
976 #define ROW_PREBUILT_FETCH_MAGIC_N 465765687
977 
978 #define ROW_MYSQL_WHOLE_ROW 0
979 #define ROW_MYSQL_REC_FIELDS 1
980 #define ROW_MYSQL_NO_TEMPLATE 2
981 #define ROW_MYSQL_DUMMY_TEMPLATE \
982   3 /* dummy template used in    \
983     row_scan_and_check_index */
984 
985 /* Values for hint_need_to_fetch_extra_cols */
986 #define ROW_RETRIEVE_PRIMARY_KEY 1
987 #define ROW_RETRIEVE_ALL_COLS 2
988 
989 /* Values for row_read_type */
990 #define ROW_READ_WITH_LOCKS 0
991 #define ROW_READ_TRY_SEMI_CONSISTENT 1
992 #define ROW_READ_DID_SEMI_CONSISTENT 2
993 
994 #ifdef UNIV_DEBUG
995 /** Wait for the background drop list to become empty. */
996 void row_wait_for_background_drop_list_empty();
997 #endif /* UNIV_DEBUG */
998 #endif /* !UNIV_HOTBACKUP */
999 
1000 #endif /* row0mysql.h */
1001