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