1 /*****************************************************************************
2
3 Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved.
4 Copyright (c) 2012, Facebook Inc.
5 Copyright (c) 2013, 2021, MariaDB Corporation.
6
7 This program is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free Software
9 Foundation; version 2 of the License.
10
11 This program is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along with
16 this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
18
19 *****************************************************************************/
20
21 /**************************************************//**
22 @file include/dict0mem.h
23 Data dictionary memory object creation
24
25 Created 1/8/1996 Heikki Tuuri
26 *******************************************************/
27
28 #ifndef dict0mem_h
29 #define dict0mem_h
30
31 #include "data0type.h"
32 #include "mem0mem.h"
33 #include "row0types.h"
34 #include "rem0types.h"
dict_col_get_mbminlen(const dict_col_t * col)35 #include "btr0types.h"
36 #include "lock0types.h"
37 #include "que0types.h"
38 #include "sync0rw.h"
39 #include "ut0mem.h"
40 #include "ut0rnd.h"
41 #include "ut0byte.h"
42 #include "hash0hash.h"
43 #include "trx0types.h"
44 #include "fts0fts.h"
45 #include "buf0buf.h"
46 #include "gis0type.h"
47 #include "fil0fil.h"
48 #include "fil0crypt.h"
49 #include <sql_const.h>
50 #include <set>
51 #include <algorithm>
52 #include <iterator>
53 #include <ostream>
54 #include <mutex>
55
56 /* Forward declaration. */
57 struct ib_rbt_t;
58
59 /** Type flags of an index: OR'ing of the flags is allowed to define a
60 combination of types */
61 /* @{ */
62 #define DICT_CLUSTERED 1 /*!< clustered index; for other than
63 auto-generated clustered indexes,
64 also DICT_UNIQUE will be set */
65 #define DICT_UNIQUE 2 /*!< unique index */
66 #define DICT_IBUF 8 /*!< insert buffer tree */
67 #define DICT_CORRUPT 16 /*!< bit to store the corrupted flag
68 in SYS_INDEXES.TYPE */
69 #define DICT_FTS 32 /* FTS index; can't be combined with the
70 other flags */
71 #define DICT_SPATIAL 64 /* SPATIAL index; can't be combined with the
72 other flags */
73 #define DICT_VIRTUAL 128 /* Index on Virtual column */
74
75 #define DICT_IT_BITS 8 /*!< number of bits used for
76 SYS_INDEXES.TYPE */
dict_col_type_assert_equal(const dict_col_t * col,const dtype_t * type)77 /* @} */
78
79 #if 0 /* not implemented, retained for history */
80 /** Types for a table object */
81 #define DICT_TABLE_ORDINARY 1 /*!< ordinary table */
82 #define DICT_TABLE_CLUSTER_MEMBER 2
83 #define DICT_TABLE_CLUSTER 3 /* this means that the table is
84 really a cluster definition */
85 #endif
86
87 /* Table and tablespace flags are generally not used for the Antelope file
88 format except for the low order bit, which is used differently depending on
89 where the flags are stored.
90
91 ==================== Low order flags bit =========================
92 | REDUNDANT | COMPACT | COMPRESSED and DYNAMIC
93 SYS_TABLES.TYPE | 1 | 1 | 1
94 dict_table_t::flags | 0 | 1 | 1
95 FSP_SPACE_FLAGS | 0 | 0 | 1
96 fil_space_t::flags | 0 | 0 | 1
97
98 Before the 5.1 plugin, SYS_TABLES.TYPE was always DICT_TABLE_ORDINARY (1)
99 and the tablespace flags field was always 0. In the 5.1 plugin, these fields
100 were repurposed to identify compressed and dynamic row formats.
101
102 The following types and constants describe the flags found in dict_table_t
103 and SYS_TABLES.TYPE. Similar flags found in fil_space_t and FSP_SPACE_FLAGS
104 are described in fsp0fsp.h. */
105
106 /* @{ */
107 /** dict_table_t::flags bit 0 is equal to 0 if the row format = Redundant */
108 #define DICT_TF_REDUNDANT 0 /*!< Redundant row format. */
109 /** dict_table_t::flags bit 0 is equal to 1 if the row format = Compact */
110 #define DICT_TF_COMPACT 1U /*!< Compact row format. */
111
112 /** This bitmask is used in SYS_TABLES.N_COLS to set and test whether
113 the Compact page format is used, i.e ROW_FORMAT != REDUNDANT */
114 #define DICT_N_COLS_COMPACT 0x80000000UL
115
116 /** Width of the COMPACT flag */
117 #define DICT_TF_WIDTH_COMPACT 1
118
119 /** Width of the ZIP_SSIZE flag */
120 #define DICT_TF_WIDTH_ZIP_SSIZE 4
121
122 /** Width of the ATOMIC_BLOBS flag. The ROW_FORMAT=REDUNDANT and
123 ROW_FORMAT=COMPACT broke up BLOB and TEXT fields, storing the first 768 bytes
124 in the clustered index. ROW_FORMAT=DYNAMIC and ROW_FORMAT=COMPRESSED
125 store the whole blob or text field off-page atomically.
126 Secondary indexes are created from this external data using row_ext_t
127 to cache the BLOB prefixes. */
128 #define DICT_TF_WIDTH_ATOMIC_BLOBS 1
129
130 /** If a table is created with the MYSQL option DATA DIRECTORY and
131 innodb-file-per-table, an older engine will not be able to find that table.
132 This flag prevents older engines from attempting to open the table and
133 allows InnoDB to update_create_info() accordingly. */
134 #define DICT_TF_WIDTH_DATA_DIR 1
135
136 /**
137 Width of the page compression flag
138 */
139 #define DICT_TF_WIDTH_PAGE_COMPRESSION 1
140 #define DICT_TF_WIDTH_PAGE_COMPRESSION_LEVEL 4
141
142 /**
143 The NO_ROLLBACK flag (3=yes; the values 1,2 used stand for
144 ATOMIC_WRITES=ON and ATOMIC_WRITES=OFF between MariaDB 10.1.0 and 10.2.3)
145 */
146 #define DICT_TF_WIDTH_NO_ROLLBACK 2
147
148 /** Width of all the currently known table flags */
149 #define DICT_TF_BITS (DICT_TF_WIDTH_COMPACT \
150 + DICT_TF_WIDTH_ZIP_SSIZE \
151 + DICT_TF_WIDTH_ATOMIC_BLOBS \
152 + DICT_TF_WIDTH_DATA_DIR \
153 + DICT_TF_WIDTH_PAGE_COMPRESSION \
154 + DICT_TF_WIDTH_PAGE_COMPRESSION_LEVEL \
155 + DICT_TF_WIDTH_NO_ROLLBACK)
156
157 /** Zero relative shift position of the COMPACT field */
158 #define DICT_TF_POS_COMPACT 0
159 /** Zero relative shift position of the ZIP_SSIZE field */
160 #define DICT_TF_POS_ZIP_SSIZE (DICT_TF_POS_COMPACT \
161 + DICT_TF_WIDTH_COMPACT)
162 /** Zero relative shift position of the ATOMIC_BLOBS field */
163 #define DICT_TF_POS_ATOMIC_BLOBS (DICT_TF_POS_ZIP_SSIZE \
164 + DICT_TF_WIDTH_ZIP_SSIZE)
165 /** Zero relative shift position of the DATA_DIR field */
166 #define DICT_TF_POS_DATA_DIR (DICT_TF_POS_ATOMIC_BLOBS \
167 + DICT_TF_WIDTH_ATOMIC_BLOBS)
168 /** Zero relative shift position of the PAGE_COMPRESSION field */
169 #define DICT_TF_POS_PAGE_COMPRESSION (DICT_TF_POS_DATA_DIR \
170 + DICT_TF_WIDTH_DATA_DIR)
171 /** Zero relative shift position of the PAGE_COMPRESSION_LEVEL field */
172 #define DICT_TF_POS_PAGE_COMPRESSION_LEVEL (DICT_TF_POS_PAGE_COMPRESSION \
173 + DICT_TF_WIDTH_PAGE_COMPRESSION)
174 /** Zero relative shift position of the NO_ROLLBACK field */
175 #define DICT_TF_POS_NO_ROLLBACK (DICT_TF_POS_PAGE_COMPRESSION_LEVEL \
176 + DICT_TF_WIDTH_PAGE_COMPRESSION_LEVEL)
177 #define DICT_TF_POS_UNUSED (DICT_TF_POS_NO_ROLLBACK \
178 + DICT_TF_WIDTH_NO_ROLLBACK)
179
180 /** Bit mask of the COMPACT field */
181 #define DICT_TF_MASK_COMPACT \
182 ((~(~0U << DICT_TF_WIDTH_COMPACT)) \
183 << DICT_TF_POS_COMPACT)
184 /** Bit mask of the ZIP_SSIZE field */
185 #define DICT_TF_MASK_ZIP_SSIZE \
186 ((~(~0U << DICT_TF_WIDTH_ZIP_SSIZE)) \
187 << DICT_TF_POS_ZIP_SSIZE)
188 /** Bit mask of the ATOMIC_BLOBS field */
189 #define DICT_TF_MASK_ATOMIC_BLOBS \
190 ((~(~0U << DICT_TF_WIDTH_ATOMIC_BLOBS)) \
191 << DICT_TF_POS_ATOMIC_BLOBS)
192 /** Bit mask of the DATA_DIR field */
193 #define DICT_TF_MASK_DATA_DIR \
194 ((~(~0U << DICT_TF_WIDTH_DATA_DIR)) \
195 << DICT_TF_POS_DATA_DIR)
196 /** Bit mask of the PAGE_COMPRESSION field */
197 #define DICT_TF_MASK_PAGE_COMPRESSION \
198 ((~(~0U << DICT_TF_WIDTH_PAGE_COMPRESSION)) \
199 << DICT_TF_POS_PAGE_COMPRESSION)
200 /** Bit mask of the PAGE_COMPRESSION_LEVEL field */
201 #define DICT_TF_MASK_PAGE_COMPRESSION_LEVEL \
202 ((~(~0U << DICT_TF_WIDTH_PAGE_COMPRESSION_LEVEL)) \
203 << DICT_TF_POS_PAGE_COMPRESSION_LEVEL)
204 /** Bit mask of the NO_ROLLBACK field */
205 #define DICT_TF_MASK_NO_ROLLBACK \
206 ((~(~0U << DICT_TF_WIDTH_NO_ROLLBACK)) \
207 << DICT_TF_POS_NO_ROLLBACK)
208
209 /** Return the value of the COMPACT field */
210 #define DICT_TF_GET_COMPACT(flags) \
211 ((flags & DICT_TF_MASK_COMPACT) \
212 >> DICT_TF_POS_COMPACT)
213 /** Return the value of the ZIP_SSIZE field */
214 #define DICT_TF_GET_ZIP_SSIZE(flags) \
215 ((flags & DICT_TF_MASK_ZIP_SSIZE) \
216 >> DICT_TF_POS_ZIP_SSIZE)
217 /** Return the value of the ATOMIC_BLOBS field */
218 #define DICT_TF_HAS_ATOMIC_BLOBS(flags) \
219 ((flags & DICT_TF_MASK_ATOMIC_BLOBS) \
220 >> DICT_TF_POS_ATOMIC_BLOBS)
221 /** Return the value of the DATA_DIR field */
222 #define DICT_TF_HAS_DATA_DIR(flags) \
223 ((flags & DICT_TF_MASK_DATA_DIR) \
224 >> DICT_TF_POS_DATA_DIR)
225 /** Return the value of the PAGE_COMPRESSION field */
226 #define DICT_TF_GET_PAGE_COMPRESSION(flags) \
227 ((flags & DICT_TF_MASK_PAGE_COMPRESSION) \
228 >> DICT_TF_POS_PAGE_COMPRESSION)
229 /** Return the value of the PAGE_COMPRESSION_LEVEL field */
230 #define DICT_TF_GET_PAGE_COMPRESSION_LEVEL(flags) \
231 ((flags & DICT_TF_MASK_PAGE_COMPRESSION_LEVEL) \
232 >> DICT_TF_POS_PAGE_COMPRESSION_LEVEL)
233
234 /* @} */
235
236 /** @brief Table Flags set number 2.
237
238 These flags will be stored in SYS_TABLES.MIX_LEN. All unused flags
239 will be written as 0. The column may contain garbage for tables
240 created with old versions of InnoDB that only implemented
241 ROW_FORMAT=REDUNDANT. InnoDB engines do not check these flags
242 for unknown bits in order to protect backward incompatibility. */
243 /* @{ */
244 /** Total number of bits in table->flags2. */
245 #define DICT_TF2_BITS 7
246 #define DICT_TF2_UNUSED_BIT_MASK (~0U << DICT_TF2_BITS)
247 #define DICT_TF2_BIT_MASK ~DICT_TF2_UNUSED_BIT_MASK
248
249 /** TEMPORARY; TRUE for tables from CREATE TEMPORARY TABLE. */
250 #define DICT_TF2_TEMPORARY 1U
251
252 /** The table has an internal defined DOC ID column */
253 #define DICT_TF2_FTS_HAS_DOC_ID 2U
254
255 /** The table has an FTS index */
256 #define DICT_TF2_FTS 4U
257
258 /** Need to add Doc ID column for FTS index build.
259 This is a transient bit for index build */
260 #define DICT_TF2_FTS_ADD_DOC_ID 8U
261
262 /** This bit is used during table creation to indicate that it will
263 use its own tablespace instead of the system tablespace. */
264 #define DICT_TF2_USE_FILE_PER_TABLE 16U
265
266 /** Set when we discard/detach the tablespace */
267 #define DICT_TF2_DISCARDED 32U
268
269 /** This bit is set if all aux table names (both common tables and
270 index tables) of a FTS table are in HEX format. */
271 #define DICT_TF2_FTS_AUX_HEX_NAME 64U
272
273 /* @} */
274
275 #define DICT_TF2_FLAG_SET(table, flag) \
276 (table->flags2 |= (flag))
277
278 #define DICT_TF2_FLAG_IS_SET(table, flag) \
279 (table->flags2 & (flag))
280
281 #define DICT_TF2_FLAG_UNSET(table, flag) \
282 (table->flags2 &= ~(flag))
283
284 /** Tables could be chained together with Foreign key constraint. When
285 first load the parent table, we would load all of its descedents.
286 This could result in rescursive calls and out of stack error eventually.
287 DICT_FK_MAX_RECURSIVE_LOAD defines the maximum number of recursive loads,
288 when exceeded, the child table will not be loaded. It will be loaded when
289 the foreign constraint check needs to be run. */
290 #define DICT_FK_MAX_RECURSIVE_LOAD 20
291
292 /** Similarly, when tables are chained together with foreign key constraints
293 with on cascading delete/update clause, delete from parent table could
294 result in recursive cascading calls. This defines the maximum number of
295 such cascading deletes/updates allowed. When exceeded, the delete from
296 parent table will fail, and user has to drop excessive foreign constraint
297 before proceeds. */
298 #define FK_MAX_CASCADE_DEL 15
299
300 /** Create a table memory object.
301 @param name table name
302 @param space tablespace
303 @param n_cols total number of columns (both virtual and non-virtual)
304 @param n_v_cols number of virtual columns
305 @param flags table flags
306 @param flags2 table flags2
307 @return own: table object */
308 dict_table_t*
309 dict_mem_table_create(
310 const char* name,
311 fil_space_t* space,
312 ulint n_cols,
313 ulint n_v_cols,
314 ulint flags,
315 ulint flags2);
316
317 /****************************************************************//**
318 Free a table memory object. */
319 void
320 dict_mem_table_free(
321 /*================*/
322 dict_table_t* table); /*!< in: table */
323 /**********************************************************************//**
324 Adds a column definition to a table. */
325 void
326 dict_mem_table_add_col(
327 /*===================*/
328 dict_table_t* table, /*!< in: table */
dict_table_n_rows_inc(dict_table_t * table)329 mem_heap_t* heap, /*!< in: temporary memory heap, or NULL */
330 const char* name, /*!< in: column name, or NULL */
331 ulint mtype, /*!< in: main datatype */
332 ulint prtype, /*!< in: precise type */
333 ulint len) /*!< in: precision */
334 MY_ATTRIBUTE((nonnull(1)));
335 /** Adds a virtual column definition to a table.
336 @param[in,out] table table
337 @param[in] heap temporary memory heap, or NULL. It is
338 used to store name when we have not finished
339 adding all columns. When all columns are
340 added, the whole name will copy to memory from
341 table->heap
342 @param[in] name column name
343 @param[in] mtype main datatype
344 @param[in] prtype precise type
345 @param[in] len length
346 @param[in] pos position in a table
dict_table_n_rows_dec(dict_table_t * table)347 @param[in] num_base number of base columns
348 @return the virtual column definition */
349 dict_v_col_t*
350 dict_mem_table_add_v_col(
351 dict_table_t* table,
352 mem_heap_t* heap,
353 const char* name,
354 ulint mtype,
355 ulint prtype,
356 ulint len,
357 ulint pos,
358 ulint num_base);
359
360 /** Adds a stored column definition to a table.
361 @param[in] table table
362 @param[in] num_base number of base columns. */
363 void
364 dict_mem_table_add_s_col(
dict_table_get_nth_col(const dict_table_t * table,ulint pos)365 dict_table_t* table,
366 ulint num_base);
367
368 /**********************************************************************//**
369 Renames a column of a table in the data dictionary cache. */
370 void
371 dict_mem_table_col_rename(
372 /*======================*/
373 dict_table_t* table, /*!< in/out: table */
374 ulint nth_col,/*!< in: column index */
375 const char* from, /*!< in: old column name */
376 const char* to, /*!< in: new column name */
377 bool is_virtual);
378 /*!< in: if this is a virtual column */
379 /**********************************************************************//**
380 This function populates a dict_col_t memory structure with
381 supplied information. */
dict_table_get_nth_v_col(const dict_table_t * table,ulint pos)382 void
383 dict_mem_fill_column_struct(
384 /*========================*/
385 dict_col_t* column, /*!< out: column struct to be
386 filled */
387 ulint col_pos, /*!< in: column position */
388 ulint mtype, /*!< in: main data type */
389 ulint prtype, /*!< in: precise type */
390 ulint col_len); /*!< in: column length */
391 /**********************************************************************//**
392 This function poplulates a dict_index_t index memory structure with
393 supplied information. */
394 UNIV_INLINE
395 void
396 dict_mem_fill_index_struct(
397 /*=======================*/
398 dict_index_t* index, /*!< out: index to be filled */
dict_table_get_sys_col(const dict_table_t * table,ulint sys)399 mem_heap_t* heap, /*!< in: memory heap */
400 const char* index_name, /*!< in: index name */
401 ulint type, /*!< in: DICT_UNIQUE,
402 DICT_CLUSTERED, ... ORed */
403 ulint n_fields); /*!< in: number of fields */
404 /**********************************************************************//**
405 Creates an index memory object.
406 @return own: index object */
407 dict_index_t*
408 dict_mem_index_create(
409 /*==================*/
410 dict_table_t* table, /*!< in: table */
411 const char* index_name, /*!< in: index name */
412 ulint type, /*!< in: DICT_UNIQUE,
413 DICT_CLUSTERED, ... ORed */
414 ulint n_fields); /*!< in: number of fields */
415 /**********************************************************************//**
416 Adds a field definition to an index. NOTE: does not take a copy
417 of the column name if the field is a column. The memory occupied
418 by the column name may be released only after publishing the index. */
dict_table_get_sys_col_no(const dict_table_t * table,ulint sys)419 void
420 dict_mem_index_add_field(
421 /*=====================*/
422 dict_index_t* index, /*!< in: index */
423 const char* name, /*!< in: column name */
424 ulint prefix_len); /*!< in: 0 or the column prefix length
425 in a MySQL index like
426 INDEX (textcol(25)) */
427 /**********************************************************************//**
428 Frees an index memory object. */
429 void
430 dict_mem_index_free(
431 /*================*/
432 dict_index_t* index); /*!< in: index */
dict_table_has_fts_index(dict_table_t * table)433 /**********************************************************************//**
434 Creates and initializes a foreign constraint memory object.
435 @return own: foreign constraint struct */
436 dict_foreign_t*
437 dict_mem_foreign_create(void);
438 /*=========================*/
439
440 /**********************************************************************//**
441 Sets the foreign_table_name_lookup pointer based on the value of
442 lower_case_table_names. If that is 0 or 1, foreign_table_name_lookup
443 will point to foreign_table_name. If 2, then another string is
444 allocated from the heap and set to lower case. */
445 void
dict_tf_is_valid_not_redundant(ulint flags)446 dict_mem_foreign_table_name_lookup_set(
447 /*===================================*/
448 dict_foreign_t* foreign, /*!< in/out: foreign struct */
449 ibool do_alloc); /*!< in: is an alloc needed */
450
451 /**********************************************************************//**
452 Sets the referenced_table_name_lookup pointer based on the value of
453 lower_case_table_names. If that is 0 or 1, referenced_table_name_lookup
454 will point to referenced_table_name. If 2, then another string is
455 allocated from the heap and set to lower case. */
456 void
457 dict_mem_referenced_table_name_lookup_set(
458 /*======================================*/
459 dict_foreign_t* foreign, /*!< in/out: foreign struct */
460 ibool do_alloc); /*!< in: is an alloc needed */
461
462 /** Fills the dependent virtual columns in a set.
463 Reason for being dependent are
464 1) FK can be present on base column of virtual columns
465 2) FK can be present on column which is a part of virtual index
466 @param[in,out] foreign foreign key information. */
467 void
468 dict_mem_foreign_fill_vcol_set(
469 dict_foreign_t* foreign);
470
471 /** Fill virtual columns set in each fk constraint present in the table.
472 @param[in,out] table innodb table object. */
473 void
474 dict_mem_table_fill_foreign_vcol_set(
475 dict_table_t* table);
476
477 /** Free the vcol_set from all foreign key constraint on the table.
478 @param[in,out] table innodb table object. */
479 void
480 dict_mem_table_free_foreign_vcol_set(
481 dict_table_t* table);
482
483 /** Create a temporary tablename like "#sql-ibNNN".
484 @param[in] heap A memory heap
485 @param[in] dbtab Table name in the form database/table name
486 @param[in] id Table id
487 @return A unique temporary tablename suitable for InnoDB use */
dict_tf_is_valid(ulint flags)488 char*
489 dict_mem_create_temporary_tablename(
490 mem_heap_t* heap,
491 const char* dbtab,
492 table_id_t id);
493
494 /** SQL identifier name wrapper for pretty-printing */
495 class id_name_t
496 {
497 public:
498 /** Default constructor */
499 id_name_t()
500 : m_name()
501 {}
502 /** Constructor
503 @param[in] name identifier to assign */
504 explicit id_name_t(
505 const char* name)
506 : m_name(name)
507 {}
508
509 /** Assignment operator
510 @param[in] name identifier to assign */
511 id_name_t& operator=(
512 const char* name)
dict_tf2_is_valid(ulint flags,ulint flags2)513 {
514 m_name = name;
515 return(*this);
516 }
517
518 /** Implicit type conversion
519 @return the name */
520 operator const char*() const
521 {
522 return(m_name);
523 }
524
525 /** Explicit type conversion
526 @return the name */
527 const char* operator()() const
528 {
529 return(m_name);
530 }
531
532 private:
533 /** The name in internal representation */
534 const char* m_name;
dict_tf_get_rec_format(ulint flags)535 };
536
537 /** Data structure for a column in a table */
538 struct dict_col_t{
539 /*----------------------*/
540 /** The following are copied from dtype_t,
541 so that all bit-fields can be packed tightly. */
542 /* @{ */
543 unsigned prtype:32; /*!< precise type; MySQL data
544 type, charset code, flags to
545 indicate nullability,
546 signedness, whether this is a
547 binary string, whether this is
548 a true VARCHAR where MySQL
549 uses 2 bytes to store the length */
550 unsigned mtype:8; /*!< main data type */
551
552 /* the remaining fields do not affect alphabetical ordering: */
553
554 unsigned len:16; /*!< length; for MySQL data this
555 is field->pack_length(),
556 except that for a >= 5.0.3
557 type true VARCHAR this is the
558 maximum byte length of the
559 string data (in addition to
560 the string, MySQL uses 1 or 2
561 bytes to store the string length) */
562
563 unsigned mbminlen:3; /*!< minimum length of a
564 character, in bytes */
dict_tf_set(ulint * flags,rec_format_t format,ulint zip_ssize,bool use_data_dir,bool page_compressed,ulint page_compression_level)565 unsigned mbmaxlen:3; /*!< maximum length of a
566 character, in bytes */
567 /*----------------------*/
568 /* End of definitions copied from dtype_t */
569 /* @} */
570
571 unsigned ind:10; /*!< table column position
572 (starting from 0) */
573 unsigned ord_part:1; /*!< nonzero if this column
574 appears in the ordering fields
575 of an index */
576 unsigned max_prefix:12; /*!< maximum index prefix length on
577 this column. Our current max limit is
578 3072 (REC_VERSION_56_MAX_INDEX_COL_LEN)
579 bytes. */
580 private:
581 /** Special value of ind for a dropped column */
582 static const unsigned DROPPED = 1023;
583 public:
584
585 /** Detach a virtual column from an index.
586 @param index being-freed index */
587 inline void detach(const dict_index_t &index);
588
589 /** Data for instantly added columns */
590 struct def_t
591 {
592 /** original default value of instantly added column */
593 const void *data;
594 /** len of data, or UNIV_SQL_DEFAULT if unavailable */
595 ulint len;
596 } def_val;
597
598 /** Retrieve the column name.
599 @param table the table of this column */
600 const char *name(const dict_table_t &table) const;
601
602 /** @return whether this is a virtual column */
603 bool is_virtual() const { return prtype & DATA_VIRTUAL; }
604 /** @return whether NULL is an allowed value for this column */
605 bool is_nullable() const { return !(prtype & DATA_NOT_NULL); }
606
607 /** @return whether table of this system field is TRX_ID-based */
608 bool vers_native() const
609 {
610 ut_ad(vers_sys_start() || vers_sys_end());
611 ut_ad(mtype == DATA_INT || mtype == DATA_FIXBINARY);
612 return mtype == DATA_INT;
613 }
614 /** @return whether this user column (not row_start, row_end)
615 has System Versioning property */
616 bool is_versioned() const { return !(~prtype & DATA_VERSIONED); }
617 /** @return whether this is the system version start */
618 bool vers_sys_start() const
619 {
620 return (prtype & DATA_VERSIONED) == DATA_VERS_START;
621 }
622 /** @return whether this is the system version end */
dict_tf_to_fsp_flags(ulint table_flags)623 bool vers_sys_end() const
624 {
625 return (prtype & DATA_VERSIONED) == DATA_VERS_END;
626 }
627
628 /** @return whether this is an instantly-added column */
629 bool is_added() const
630 {
631 DBUG_ASSERT(def_val.len != UNIV_SQL_DEFAULT || !def_val.data);
632 return def_val.len != UNIV_SQL_DEFAULT;
633 }
634 /** Flag the column instantly dropped */
635 void set_dropped() { ind = DROPPED; }
636 /** Flag the column instantly dropped.
637 @param not_null whether the column was NOT NULL
638 @param len2 whether the length exceeds 255 bytes
639 @param fixed_len the fixed length in bytes, or 0 */
640 void set_dropped(bool not_null, bool len2, unsigned fixed)
641 {
642 DBUG_ASSERT(!len2 || !fixed);
643 prtype= not_null ? DATA_NOT_NULL | DATA_BINARY_TYPE : DATA_BINARY_TYPE;
644 if (fixed)
645 {
646 mtype= DATA_FIXBINARY;
647 len= fixed;
648 }
649 else
650 {
651 mtype= DATA_BINARY;
652 len= len2 ? 65535 : 255;
653 }
654 mbminlen= mbmaxlen= 0;
655 ind= DROPPED;
656 ord_part= 0;
657 max_prefix= 0;
658 }
659 /** @return whether the column was instantly dropped */
660 bool is_dropped() const { return ind == DROPPED; }
661 /** @return whether the column was instantly dropped
662 @param index the clustered index */
663 inline bool is_dropped(const dict_index_t &index) const;
664
665 /** Get the default value of an instantly-added column.
666 @param[out] len value length (in bytes), or UNIV_SQL_NULL
667 @return default value
668 @retval NULL if the default value is SQL NULL (len=UNIV_SQL_NULL) */
669 const byte *instant_value(ulint *len) const
670 {
671 DBUG_ASSERT(is_added());
672 *len= def_val.len;
673 return static_cast<const byte*>(def_val.data);
674 }
675
676 /** Remove the 'instant ADD' status of the column */
677 void clear_instant()
678 {
679 def_val.len= UNIV_SQL_DEFAULT;
680 def_val.data= NULL;
681 }
682
683 /** @return whether two columns have compatible data type encoding */
684 bool same_type(const dict_col_t &other) const
dict_tf_to_sys_tables_type(ulint flags)685 {
686 if (mtype != other.mtype)
687 {
688 /* For latin1_swedish_ci, DATA_CHAR and DATA_VARCHAR
689 will be used instead of DATA_MYSQL and DATA_VARMYSQL.
690 As long as mtype,prtype are being written to InnoDB
691 data dictionary tables, we cannot simplify this. */
692 switch (mtype) {
693 default:
694 return false;
695 case DATA_VARCHAR:
696 if (other.mtype != DATA_VARMYSQL)
697 return false;
698 goto check_encoding;
699 case DATA_VARMYSQL:
700 if (other.mtype != DATA_VARCHAR)
701 return false;
702 goto check_encoding;
703 case DATA_CHAR:
704 if (other.mtype != DATA_MYSQL)
705 return false;
706 goto check_encoding;
707 case DATA_MYSQL:
708 if (other.mtype != DATA_CHAR)
709 return false;
710 goto check_encoding;
711 }
712 }
713 else if (dtype_is_string_type(mtype))
714 {
715 check_encoding:
716 const uint16_t cset= dtype_get_charset_coll(prtype);
717 const uint16_t ocset= dtype_get_charset_coll(other.prtype);
718 return cset == ocset || dict_col_t::same_encoding(cset, ocset);
719 }
720
721 return true;
722 }
723
724 /** @return whether two collations codes have the same character encoding */
725 static bool same_encoding(uint16_t a, uint16_t b);
726
727 /** Determine if the columns have the same format
728 except for is_nullable() and is_versioned().
729 @param other column to compare to
730 @return whether the columns have the same format */
731 bool same_format(const dict_col_t &other) const
732 {
733 return same_type(other) && len >= other.len &&
734 mbminlen == other.mbminlen && mbmaxlen >= other.mbmaxlen &&
735 !((prtype ^ other.prtype) & ~(DATA_NOT_NULL | DATA_VERSIONED |
dict_index_get_n_fields(const dict_index_t * index)736 CHAR_COLL_MASK << 16 |
737 DATA_LONG_TRUE_VARCHAR));
738 }
739
740 /** @return whether the column values are comparable by memcmp() */
741 bool is_binary() const { return prtype & DATA_BINARY_TYPE; }
742 };
743
744 /** Index information put in a list of virtual column structure. Index
745 id and virtual column position in the index will be logged.
746 There can be multiple entries for a given index, with a different position. */
747 struct dict_v_idx_t {
748 /** active index on the column */
749 dict_index_t* index;
750
751 /** position in this index */
752 ulint nth_field;
753
dict_index_get_n_unique(const dict_index_t * index)754 dict_v_idx_t(dict_index_t* index, ulint nth_field)
755 : index(index), nth_field(nth_field) {}
756 };
757
758 /** Data structure for a virtual column in a table */
759 struct dict_v_col_t{
760 /** column structure */
761 dict_col_t m_col;
762
763 /** array of base column ptr */
764 dict_col_t** base_col;
765
766 /** number of base column */
767 unsigned num_base:10;
768
769 /** column pos in table */
770 unsigned v_pos:10;
dict_index_get_n_unique_in_tree(const dict_index_t * index)771
772 /** Virtual index list, and column position in the index */
773 std::forward_list<dict_v_idx_t, ut_allocator<dict_v_idx_t> >
774 v_indexes;
775
776 /** Detach the column from an index.
777 @param index index to be detached from */
778 void detach(const dict_index_t &index)
779 {
780 if (v_indexes.empty()) return;
781 auto i= v_indexes.before_begin();
782 do {
783 auto prev = i++;
784 if (i == v_indexes.end())
785 {
786 return;
787 }
788 if (i->index == &index)
789 {
790 v_indexes.erase_after(prev);
791 return;
792 }
793 }
794 while (i != v_indexes.end());
795 }
dict_index_get_n_unique_in_tree_nonleaf(const dict_index_t * index)796 };
797
798 /** Data structure for newly added virtual column in a index.
799 It is used only during rollback_inplace_alter_table() of
800 addition of index depending on newly added virtual columns
801 and uses index heap. Should be freed when index is being
802 removed from cache. */
803 struct dict_add_v_col_info
804 {
805 ulint n_v_col;
806 dict_v_col_t *v_col;
807
808 /** Add the newly added virtual column while rollbacking
809 the index which contains new virtual columns
810 @param col virtual column to be duplicated
811 @param offset offset where to duplicate virtual column */
812 dict_v_col_t* add_drop_v_col(mem_heap_t *heap, dict_v_col_t *col,
813 ulint offset)
814 {
815 ut_ad(n_v_col);
816 ut_ad(offset < n_v_col);
817 if (!v_col)
818 v_col= static_cast<dict_v_col_t*>
819 (mem_heap_alloc(heap, n_v_col * sizeof *v_col));
dict_index_get_n_ordering_defined_by_user(const dict_index_t * index)820 new (&v_col[offset]) dict_v_col_t();
821 v_col[offset].m_col= col->m_col;
822 v_col[offset].v_pos= col->v_pos;
823 return &v_col[offset];
824 }
825 };
826
827 /** Data structure for newly added virtual column in a table */
828 struct dict_add_v_col_t{
829 /** number of new virtual column */
830 ulint n_v_col;
831
832 /** column structures */
833 const dict_v_col_t* v_col;
dict_index_get_nth_field(const dict_index_t * index,ulint pos)834
835 /** new col names */
836 const char** v_col_name;
837 };
838
839 /** Data structure for a stored column in a table. */
840 struct dict_s_col_t {
841 /** Stored column ptr */
842 dict_col_t* m_col;
843 /** array of base col ptr */
844 dict_col_t** base_col;
845 /** number of base columns */
846 ulint num_base;
847 /** column pos in table */
848 ulint s_pos;
849 };
850
dict_field_get_col(const dict_field_t * field)851 /** list to put stored column for create_table_info_t */
852 typedef std::forward_list<dict_s_col_t, ut_allocator<dict_s_col_t> >
853 dict_s_col_list;
854
855 /** @brief DICT_ANTELOPE_MAX_INDEX_COL_LEN is measured in bytes and
856 is the maximum indexed column length (or indexed prefix length) in
857 ROW_FORMAT=REDUNDANT and ROW_FORMAT=COMPACT. Also, in any format,
858 any fixed-length field that is longer than this will be encoded as
859 a variable-length field.
860
861 It is set to 3*256, so that one can create a column prefix index on
862 256 characters of a TEXT or VARCHAR column also in the UTF-8
dict_index_get_nth_col(const dict_index_t * index,ulint pos)863 charset. In that charset, a character may take at most 3 bytes. This
864 constant MUST NOT BE CHANGED, or the compatibility of InnoDB data
865 files would be at risk! */
866 #define DICT_ANTELOPE_MAX_INDEX_COL_LEN REC_ANTELOPE_MAX_INDEX_COL_LEN
867
868 /** Find out maximum indexed column length by its table format.
869 For ROW_FORMAT=REDUNDANT and ROW_FORMAT=COMPACT, the maximum
870 field length is REC_ANTELOPE_MAX_INDEX_COL_LEN - 1 (767). For
871 ROW_FORMAT=COMPRESSED and ROW_FORMAT=DYNAMIC, the length could
872 be REC_VERSION_56_MAX_INDEX_COL_LEN (3072) bytes */
873 #define DICT_MAX_FIELD_LEN_BY_FORMAT(table) \
874 (dict_table_has_atomic_blobs(table) \
875 ? REC_VERSION_56_MAX_INDEX_COL_LEN \
876 : REC_ANTELOPE_MAX_INDEX_COL_LEN - 1)
877
878 #define DICT_MAX_FIELD_LEN_BY_FORMAT_FLAG(flags) \
879 (DICT_TF_HAS_ATOMIC_BLOBS(flags) \
880 ? REC_VERSION_56_MAX_INDEX_COL_LEN \
881 : REC_ANTELOPE_MAX_INDEX_COL_LEN - 1)
882
883 /** Defines the maximum fixed length column size */
884 #define DICT_MAX_FIXED_COL_LEN DICT_ANTELOPE_MAX_INDEX_COL_LEN
885
886 #ifdef WITH_WSREP
887 #define WSREP_MAX_SUPPORTED_KEY_LENGTH 3500
888 #endif /* WITH_WSREP */
889
890 /** Data structure for a field in an index */
891 struct dict_field_t{
892 dict_col_t* col; /*!< pointer to the table column */
893 id_name_t name; /*!< name of the column */
894 unsigned prefix_len:12; /*!< 0 or the length of the column
895 prefix in bytes in a MySQL index of
896 type, e.g., INDEX (textcol(25));
897 must be smaller than
898 DICT_MAX_FIELD_LEN_BY_FORMAT;
899 NOTE that in the UTF-8 charset, MySQL
900 sets this to (mbmaxlen * the prefix len)
901 in UTF-8 chars */
902 unsigned fixed_len:10; /*!< 0 or the fixed length of the
903 column if smaller than
904 DICT_ANTELOPE_MAX_INDEX_COL_LEN */
905
906 /** Zero-initialize all fields */
907 dict_field_t() : col(NULL), name(NULL), prefix_len(0), fixed_len(0) {}
908
909 /** Check whether two index fields are equivalent.
910 @param[in] old the other index field
911 @return whether the index fields are equivalent */
912 bool same(const dict_field_t& other) const
913 {
914 return(prefix_len == other.prefix_len
915 && fixed_len == other.fixed_len);
916 }
917 };
918
919 /**********************************************************************//**
920 PADDING HEURISTIC BASED ON LINEAR INCREASE OF PADDING TO AVOID
921 COMPRESSION FAILURES
922 (Note: this is relevant only for compressed indexes)
923 GOAL: Avoid compression failures by maintaining information about the
924 compressibility of data. If data is not very compressible then leave
dict_index_get_page(const dict_index_t * index)925 some extra space 'padding' in the uncompressed page making it more
926 likely that compression of less than fully packed uncompressed page will
927 succeed.
928
929 This padding heuristic works by increasing the pad linearly until the
930 desired failure rate is reached. A "round" is a fixed number of
931 compression operations.
932 After each round, the compression failure rate for that round is
933 computed. If the failure rate is too high, then padding is incremented
934 by a fixed value, otherwise it's left intact.
935 If the compression failure is lower than the desired rate for a fixed
936 number of consecutive rounds, then the padding is decreased by a fixed
937 value. This is done to prevent overshooting the padding value,
938 and to accommodate the possible change in data compressibility. */
939
940 /** Number of zip ops in one round. */
941 #define ZIP_PAD_ROUND_LEN (128)
942
943 /** Number of successful rounds after which the padding is decreased */
944 #define ZIP_PAD_SUCCESSFUL_ROUND_LIMIT (5)
945
946 /** Amount by which padding is increased. */
947 #define ZIP_PAD_INCR (128)
948
949 /** Percentage of compression failures that are allowed in a single
950 round */
951 extern ulong zip_failure_threshold_pct;
952
953 /** Maximum percentage of a page that can be allowed as a pad to avoid
954 compression failures */
dict_index_get_space_reserve(void)955 extern ulong zip_pad_max;
956
957 /** Data structure to hold information about about how much space in
958 an uncompressed page should be left as padding to avoid compression
959 failures. This estimate is based on a self-adapting heuristic. */
960 struct zip_pad_info_t {
961 /** Dummy assignment operator for dict_index_t::clone() */
962 zip_pad_info_t &operator=(const zip_pad_info_t&) { return *this; }
963 std::mutex mutex; /*!< mutex protecting the info */
964 Atomic_relaxed<ulint>
965 pad; /*!< number of bytes used as pad */
dict_index_get_online_status(const dict_index_t * index)966 ulint success;/*!< successful compression ops during
967 current round */
968 ulint failure;/*!< failed compression ops during
969 current round */
970 ulint n_rounds;/*!< number of currently successful
971 rounds */
972 };
973
974 /** Number of samples of data size kept when page compression fails for
975 a certain index.*/
976 #define STAT_DEFRAG_DATA_SIZE_N_SAMPLE 10
977
978 /** "GEN_CLUST_INDEX" is the name reserved for InnoDB default
979 system clustered index when there is no primary key. */
980 const char innobase_index_reserve_name[] = "GEN_CLUST_INDEX";
981
982 /** Data structure for an index. Most fields will be
983 initialized to 0, NULL or FALSE in dict_mem_index_create(). */
984 struct dict_index_t {
985 index_id_t id; /*!< id of the index */
986 mem_heap_t* heap; /*!< memory heap */
987 id_name_t name; /*!< index name */
988 dict_table_t* table; /*!< back pointer to table */
989 /** root page number, or FIL_NULL if the index has been detached
990 from storage (DISCARD TABLESPACE or similar),
991 or 1 if the index is in table->freed_indexes */
992 unsigned page:32;
993 unsigned merge_threshold:6;
994 /*!< In the pessimistic delete, if the page
995 data size drops below this limit in percent,
996 merging it to a neighbor is tried */
997 # define DICT_INDEX_MERGE_THRESHOLD_DEFAULT 50
dict_index_set_online_status(dict_index_t * index,enum online_index_status status)998 unsigned type:DICT_IT_BITS;
999 /*!< index type (DICT_CLUSTERED, DICT_UNIQUE,
1000 DICT_IBUF, DICT_CORRUPT) */
1001 #define MAX_KEY_LENGTH_BITS 12
1002 unsigned trx_id_offset:MAX_KEY_LENGTH_BITS;
1003 /*!< position of the trx id column
1004 in a clustered index record, if the fields
1005 before it are known to be of a fixed size,
1006 0 otherwise */
1007 #if (1<<MAX_KEY_LENGTH_BITS) < HA_MAX_KEY_LENGTH
1008 # error (1<<MAX_KEY_LENGTH_BITS) < HA_MAX_KEY_LENGTH
1009 #endif
1010 unsigned n_user_defined_cols:10;
1011 /*!< number of columns the user defined to
1012 be in the index: in the internal
1013 representation we add more columns */
1014 unsigned nulls_equal:1;
1015 /*!< if true, SQL NULL == SQL NULL */
1016 #ifdef BTR_CUR_HASH_ADAPT
1017 #ifdef MYSQL_INDEX_DISABLE_AHI
1018 unsigned disable_ahi:1;
1019 /*!< whether to disable the
1020 adaptive hash index.
1021 Maybe this could be disabled for
1022 temporary tables? */
1023 #endif
1024 #endif /* BTR_CUR_HASH_ADAPT */
1025 unsigned n_uniq:10;/*!< number of fields from the beginning
1026 which are enough to determine an index
1027 entry uniquely */
1028 unsigned n_def:10;/*!< number of fields defined so far */
1029 unsigned n_fields:10;/*!< number of fields in the index */
1030 unsigned n_nullable:10;/*!< number of nullable fields */
1031 unsigned n_core_fields:10;/*!< number of fields in the index
1032 (before the first time of instant add columns) */
dict_index_is_online_ddl(const dict_index_t * index)1033 /** number of bytes of null bits in ROW_FORMAT!=REDUNDANT node pointer
1034 records; usually equal to UT_BITS_IN_BYTES(n_nullable), but
1035 can be less in clustered indexes with instant ADD COLUMN */
1036 unsigned n_core_null_bytes:8;
1037 /** magic value signalling that n_core_null_bytes was not
1038 initialized yet */
1039 static const unsigned NO_CORE_NULL_BYTES = 0xff;
1040 /** The clustered index ID of the hard-coded SYS_INDEXES table. */
1041 static const unsigned DICT_INDEXES_ID = 3;
1042 unsigned cached:1;/*!< TRUE if the index object is in the
1043 dictionary cache */
1044 unsigned to_be_dropped:1;
1045 /*!< TRUE if the index is to be dropped;
1046 protected by dict_sys.latch */
1047 unsigned online_status:2;
1048 /*!< enum online_index_status.
1049 Transitions from ONLINE_INDEX_COMPLETE (to
1050 ONLINE_INDEX_CREATION) are protected
1051 by dict_sys.latch and
1052 dict_sys.mutex. Other changes are
1053 protected by index->lock. */
1054 unsigned uncommitted:1;
1055 /*!< a flag that is set for secondary indexes
1056 that have not been committed to the
1057 data dictionary yet */
1058
1059 #ifdef UNIV_DEBUG
1060 /** whether this is a dummy index object */
1061 bool is_dummy;
dict_table_is_fts_column(ib_vector_t * indexes,ulint col_no,bool is_virtual)1062 /** whether btr_cur_instant_init() is in progress */
1063 bool in_instant_init;
1064 uint32_t magic_n;/*!< magic number */
1065 /** Value of dict_index_t::magic_n */
1066 # define DICT_INDEX_MAGIC_N 76789786
1067 #endif
1068 dict_field_t* fields; /*!< array of field descriptions */
1069 st_mysql_ftparser*
1070 parser; /*!< fulltext parser plugin */
1071
1072 /** It just indicates whether newly added virtual column
1073 during alter. It stores column in case of alter failure.
1074 It should use heap from dict_index_t. It should be freed
1075 while removing the index from table. */
1076 dict_add_v_col_info* new_vcol_info;
1077
1078 bool index_fts_syncing;/*!< Whether the fts index is
1079 still syncing in the background;
1080 FIXME: remove this and use MDL */
1081 UT_LIST_NODE_T(dict_index_t)
1082 indexes;/*!< list of indexes of the table */
1083 #ifdef BTR_CUR_ADAPT
1084 btr_search_t* search_info;
1085 /*!< info used in optimistic searches */
1086 #endif /* BTR_CUR_ADAPT */
1087 row_log_t* online_log;
1088 /*!< the log of modifications
1089 during online index creation;
1090 valid when online_status is
dict_max_field_len_store_undo(dict_table_t * table,const dict_col_t * col)1091 ONLINE_INDEX_CREATION */
1092 /*----------------------*/
1093 /** Statistics for query optimization */
1094 /* @{ */
1095 ib_uint64_t* stat_n_diff_key_vals;
1096 /*!< approximate number of different
1097 key values for this index, for each
1098 n-column prefix where 1 <= n <=
1099 dict_get_n_unique(index) (the array is
1100 indexed from 0 to n_uniq-1); we
1101 periodically calculate new
1102 estimates */
1103 ib_uint64_t* stat_n_sample_sizes;
1104 /*!< number of pages that were sampled
1105 to calculate each of stat_n_diff_key_vals[],
1106 e.g. stat_n_sample_sizes[3] pages were sampled
1107 to get the number stat_n_diff_key_vals[3]. */
1108 ib_uint64_t* stat_n_non_null_key_vals;
1109 /* approximate number of non-null key values
1110 for this index, for each column where
1111 1 <= n <= dict_get_n_unique(index) (the array
1112 is indexed from 0 to n_uniq-1); This
1113 is used when innodb_stats_method is
1114 "nulls_ignored". */
dict_max_v_field_len_store_undo(dict_table_t * table,ulint col_no)1115 ulint stat_index_size;
1116 /*!< approximate index size in
1117 database pages */
1118 ulint stat_n_leaf_pages;
1119 /*!< approximate number of leaf pages in the
1120 index tree */
1121 bool stats_error_printed;
1122 /*!< has persistent statistics error printed
1123 for this index ? */
1124 /* @} */
1125 /** Statistics for defragmentation, these numbers are estimations and
1126 could be very inaccurate at certain times, e.g. right after restart,
1127 during defragmentation, etc. */
1128 /* @{ */
1129 ulint stat_defrag_modified_counter;
1130 ulint stat_defrag_n_pages_freed;
1131 /* number of pages freed by defragmentation. */
1132 ulint stat_defrag_n_page_split;
1133 /* number of page splits since last full index
1134 defragmentation. */
1135 ulint stat_defrag_data_size_sample[STAT_DEFRAG_DATA_SIZE_N_SAMPLE];
1136 /* data size when compression failure happened
1137 the most recent 10 times. */
1138 ulint stat_defrag_sample_next_slot;
1139 /* in which slot the next sample should be
1140 saved. */
1141 /* @} */
1142 private:
1143 /** R-tree split sequence number */
1144 Atomic_relaxed<node_seq_t> rtr_ssn;
1145 public:
dict_table_is_corrupted(const dict_table_t * table)1146 void set_ssn(node_seq_t ssn) { rtr_ssn= ssn; }
1147 node_seq_t assign_ssn() { return rtr_ssn.fetch_add(1) + 1; }
1148 node_seq_t ssn() const { return rtr_ssn; }
1149
1150 rtr_info_track_t*
1151 rtr_track;/*!< tracking all R-Tree search cursors */
1152 trx_id_t trx_id; /*!< id of the transaction that created this
1153 index, or 0 if the index existed
1154 when InnoDB was started up */
1155 zip_pad_info_t zip_pad;/*!< Information about state of
1156 compression failures and successes */
1157 mutable rw_lock_t lock; /*!< read-write lock protecting the
1158 upper levels of the index tree */
1159
1160 /** Determine if the index has been committed to the
1161 data dictionary.
1162 @return whether the index definition has been committed */
1163 bool is_committed() const
1164 {
1165 ut_ad(!uncommitted || !(type & DICT_CLUSTERED));
1166 return(UNIV_LIKELY(!uncommitted));
1167 }
1168
1169 /** Flag an index committed or uncommitted.
1170 @param[in] committed whether the index is committed */
1171 void set_committed(bool committed)
dict_table_is_file_per_table(const dict_table_t * table)1172 {
1173 ut_ad(!to_be_dropped);
1174 ut_ad(committed || !(type & DICT_CLUSTERED));
1175 uncommitted = !committed;
1176 }
1177
1178 /** Notify that the index pages are going to be modified.
1179 @param[in,out] mtr mini-transaction */
1180 inline void set_modified(mtr_t& mtr) const;
1181
acquire()1182 /** @return whether this index is readable
1183 @retval true normally
1184 @retval false if this is a single-table tablespace
1185 and the .ibd file is missing, or a
1186 page cannot be read or decrypted */
1187 inline bool is_readable() const;
1188
1189 /** @return whether instant ALTER TABLE is in effect */
1190 inline bool is_instant() const;
1191
release()1192 /** @return whether the index is the primary key index
1193 (not the clustered index of the change buffer) */
1194 bool is_primary() const
1195 {
1196 return DICT_CLUSTERED == (type & (DICT_CLUSTERED | DICT_IBUF));
1197 }
1198
1199 /** @return whether this is a generated clustered index */
1200 bool is_gen_clust() const { return type == DICT_CLUSTERED; }
1201
1202 /** @return whether this is a clustered index */
1203 bool is_clust() const { return type & DICT_CLUSTERED; }
1204
1205 /** @return whether this is a unique index */
1206 bool is_unique() const { return type & DICT_UNIQUE; }
dict_table_encode_n_col(ulint n_col,ulint n_v_col)1207
1208 /** @return whether this is a spatial index */
1209 bool is_spatial() const { return UNIV_UNLIKELY(type & DICT_SPATIAL); }
1210
1211 /** @return whether this is the change buffer */
1212 bool is_ibuf() const { return UNIV_UNLIKELY(type & DICT_IBUF); }
1213
1214 /** @return whether the index includes virtual columns */
1215 bool has_virtual() const { return type & DICT_VIRTUAL; }
1216
1217 /** @return the position of DB_TRX_ID */
1218 unsigned db_trx_id() const {
1219 DBUG_ASSERT(is_primary());
dict_table_decode_n_col(ulint encoded,ulint * n_col,ulint * n_v_col)1220 DBUG_ASSERT(n_uniq);
1221 DBUG_ASSERT(n_uniq <= MAX_REF_PARTS);
1222 return n_uniq;
1223 }
1224 /** @return the position of DB_ROLL_PTR */
1225 unsigned db_roll_ptr() const { return db_trx_id() + 1; }
1226
1227 /** @return the offset of the metadata BLOB field,
1228 or the first user field after the PRIMARY KEY,DB_TRX_ID,DB_ROLL_PTR */
1229 unsigned first_user_field() const { return db_trx_id() + 2; }
1230
1231 /** @return whether the index is corrupted */
1232 inline bool is_corrupted() const;
1233
dict_free_vc_templ(dict_vcol_templ_t * vc_templ)1234 /** Detach the virtual columns from the index that is to be removed. */
1235 void detach_columns()
1236 {
1237 if (!has_virtual() || !cached)
1238 return;
1239 for (unsigned i= 0; i < n_fields; i++)
1240 {
1241 dict_col_t* col= fields[i].col;
1242 if (!col || !col->is_virtual())
1243 continue;
1244 col->detach(*this);
1245 }
1246 }
1247
1248 /** Determine how many fields of a given prefix can be set NULL.
1249 @param[in] n_prefix number of fields in the prefix
1250 @return number of fields 0..n_prefix-1 that can be set NULL */
1251 unsigned get_n_nullable(ulint n_prefix) const
1252 {
1253 DBUG_ASSERT(n_prefix > 0);
1254 DBUG_ASSERT(n_prefix <= n_fields);
1255 unsigned n = n_nullable;
1256 for (; n_prefix < n_fields; n_prefix++) {
1257 const dict_col_t* col = fields[n_prefix].col;
dict_table_have_virtual_index(dict_table_t * table)1258 DBUG_ASSERT(!col->is_virtual());
1259 n -= col->is_nullable();
1260 }
1261 DBUG_ASSERT(n < n_def);
1262 return n;
1263 }
1264
1265 /** Get the default value of an instantly-added clustered index field.
1266 @param[in] n instantly added field position
1267 @param[out] len value length (in bytes), or UNIV_SQL_NULL
1268 @return default value
1269 @retval NULL if the default value is SQL NULL (len=UNIV_SQL_NULL) */
1270 const byte* instant_field_value(ulint n, ulint* len) const
1271 {
1272 DBUG_ASSERT(is_instant() || id == DICT_INDEXES_ID);
1273 DBUG_ASSERT(n + (id == DICT_INDEXES_ID) >= n_core_fields);
1274 DBUG_ASSERT(n < n_fields);
1275 return fields[n].col->instant_value(len);
1276 }
1277
1278 /** Adjust index metadata for instant ADD/DROP/reorder COLUMN.
1279 @param[in] clustered index definition after instant ALTER TABLE */
1280 inline void instant_add_field(const dict_index_t& instant);
1281 /** Remove instant ADD COLUMN metadata. */
1282 inline void clear_instant_add();
1283 /** Remove instant ALTER TABLE metadata. */
1284 inline void clear_instant_alter();
1285
1286 /** Construct the metadata record for instant ALTER TABLE.
1287 @param[in] row dummy or default values for existing columns
1288 @param[in,out] heap memory heap for allocations
1289 @return metadata record */
1290 inline dtuple_t*
1291 instant_metadata(const dtuple_t& row, mem_heap_t* heap) const;
1292
1293 /** Check if record in clustered index is historical row.
1294 @param[in] rec clustered row
1295 @param[in] offsets offsets
1296 @return true if row is historical */
1297 bool
1298 vers_history_row(const rec_t* rec, const rec_offs* offsets);
1299
1300 /** Check if record in secondary index is historical row.
1301 @param[in] rec record in a secondary index
1302 @param[out] history_row true if row is historical
1303 @return true on error */
1304 bool
1305 vers_history_row(const rec_t* rec, bool &history_row);
1306
1307 /** Assign the number of new column to be added as a part
1308 of the index
1309 @param n_vcol number of virtual columns to be added */
1310 void assign_new_v_col(ulint n_vcol)
1311 {
1312 new_vcol_info= static_cast<dict_add_v_col_info*>
1313 (mem_heap_zalloc(heap, sizeof *new_vcol_info));
1314 new_vcol_info->n_v_col= n_vcol;
1315 }
1316
1317 /* @return whether index has new virtual column */
1318 bool has_new_v_col() const { return new_vcol_info; }
1319
1320 /* @return number of newly added virtual column */
1321 ulint get_new_n_vcol() const
1322 { return new_vcol_info ? new_vcol_info->n_v_col : 0; }
1323
1324 /** Reconstruct the clustered index fields.
1325 @return whether metadata is incorrect */
1326 inline bool reconstruct_fields();
1327
1328 /** Check if the index contains a column or a prefix of that column.
1329 @param[in] n column number
1330 @param[in] is_virtual whether it is a virtual col
1331 @return whether the index contains the column or its prefix */
1332 bool contains_col_or_prefix(ulint n, bool is_virtual) const
1333 MY_ATTRIBUTE((warn_unused_result));
1334
1335 #ifdef BTR_CUR_HASH_ADAPT
1336 /** @return a clone of this */
1337 dict_index_t* clone() const;
1338 /** Clone this index for lazy dropping of the adaptive hash index.
1339 @return this or a clone */
1340 dict_index_t* clone_if_needed();
1341 /** @return number of leaf pages pointed to by the adaptive hash index */
1342 inline ulint n_ahi_pages() const;
1343 /** @return whether mark_freed() had been invoked */
1344 bool freed() const { return UNIV_UNLIKELY(page == 1); }
1345 /** Note that the index is waiting for btr_search_lazy_free() */
1346 void set_freed() { ut_ad(!freed()); page= 1; }
1347 #endif /* BTR_CUR_HASH_ADAPT */
1348
1349 /** This ad-hoc class is used by record_size_info only. */
1350 class record_size_info_t {
1351 public:
1352 record_size_info_t()
1353 : max_leaf_size(0), shortest_size(0), too_big(false),
1354 first_overrun_field_index(SIZE_T_MAX), overrun_size(0)
1355 {
1356 }
1357
1358 /** Mark row potentially too big for page and set up first
1359 overflow field index. */
1360 void set_too_big(size_t field_index)
1361 {
1362 ut_ad(field_index != SIZE_T_MAX);
1363
1364 too_big = true;
1365 if (first_overrun_field_index > field_index) {
1366 first_overrun_field_index = field_index;
1367 overrun_size = shortest_size;
1368 }
1369 }
1370
1371 /** @return overrun field index or SIZE_T_MAX if nothing
1372 overflowed*/
1373 size_t get_first_overrun_field_index() const
1374 {
1375 ut_ad(row_is_too_big());
1376 ut_ad(first_overrun_field_index != SIZE_T_MAX);
1377 return first_overrun_field_index;
1378 }
1379
1380 size_t get_overrun_size() const
1381 {
1382 ut_ad(row_is_too_big());
1383 return overrun_size;
1384 }
1385
1386 bool row_is_too_big() const { return too_big; }
1387
1388 size_t max_leaf_size; /** Bigger row size this index can
1389 produce */
1390 size_t shortest_size; /** shortest because it counts everything
1391 as in overflow pages */
1392
1393 private:
1394 bool too_big; /** This one is true when maximum row size this
1395 index can produce is bigger than maximum row
1396 size given page can hold. */
1397 size_t first_overrun_field_index; /** After adding this field
1398 index row overflowed maximum
1399 allowed size. Useful for
1400 reporting back to user. */
1401 size_t overrun_size; /** Just overrun row size */
1402 };
1403
1404 /** Returns max possibly record size for that index, size of a shortest
1405 everything in overflow) size of the longest possible row and index
1406 of a field which made index records too big to fit on a page.*/
1407 inline record_size_info_t record_size_info() const;
1408 };
1409
1410 /** Detach a virtual column from an index.
1411 @param index being-freed index */
1412 inline void dict_col_t::detach(const dict_index_t &index)
1413 {
1414 if (is_virtual())
1415 reinterpret_cast<dict_v_col_t*>(this)->detach(index);
1416 }
1417
1418 /** The status of online index creation */
1419 enum online_index_status {
1420 /** the index is complete and ready for access */
1421 ONLINE_INDEX_COMPLETE = 0,
1422 /** the index is being created, online
1423 (allowing concurrent modifications) */
1424 ONLINE_INDEX_CREATION,
1425 /** secondary index creation was aborted and the index
1426 should be dropped as soon as index->table->n_ref_count reaches 0,
1427 or online table rebuild was aborted and the clustered index
1428 of the original table should soon be restored to
1429 ONLINE_INDEX_COMPLETE */
1430 ONLINE_INDEX_ABORTED,
1431 /** the online index creation was aborted, the index was
1432 dropped from the data dictionary and the tablespace, and it
1433 should be dropped from the data dictionary cache as soon as
1434 index->table->n_ref_count reaches 0. */
1435 ONLINE_INDEX_ABORTED_DROPPED
1436 };
1437
1438 /** Set to store the virtual columns which are affected by Foreign
1439 key constraint. */
1440 typedef std::set<dict_v_col_t*, std::less<dict_v_col_t*>,
1441 ut_allocator<dict_v_col_t*> > dict_vcol_set;
1442
1443 /** Data structure for a foreign key constraint; an example:
1444 FOREIGN KEY (A, B) REFERENCES TABLE2 (C, D). Most fields will be
1445 initialized to 0, NULL or FALSE in dict_mem_foreign_create(). */
1446 struct dict_foreign_t{
1447 mem_heap_t* heap; /*!< this object is allocated from
1448 this memory heap */
1449 char* id; /*!< id of the constraint as a
1450 null-terminated string */
1451 unsigned n_fields:10; /*!< number of indexes' first fields
1452 for which the foreign key
1453 constraint is defined: we allow the
1454 indexes to contain more fields than
1455 mentioned in the constraint, as long
1456 as the first fields are as mentioned */
1457 unsigned type:6; /*!< 0 or DICT_FOREIGN_ON_DELETE_CASCADE
1458 or DICT_FOREIGN_ON_DELETE_SET_NULL */
1459 char* foreign_table_name;/*!< foreign table name */
1460 char* foreign_table_name_lookup;
1461 /*!< foreign table name used for dict lookup */
1462 dict_table_t* foreign_table; /*!< table where the foreign key is */
1463 const char** foreign_col_names;/*!< names of the columns in the
1464 foreign key */
1465 char* referenced_table_name;/*!< referenced table name */
1466 char* referenced_table_name_lookup;
1467 /*!< referenced table name for dict lookup*/
1468 dict_table_t* referenced_table;/*!< table where the referenced key
1469 is */
1470 const char** referenced_col_names;/*!< names of the referenced
1471 columns in the referenced table */
1472 dict_index_t* foreign_index; /*!< foreign index; we require that
1473 both tables contain explicitly defined
1474 indexes for the constraint: InnoDB
1475 does not generate new indexes
1476 implicitly */
1477 dict_index_t* referenced_index;/*!< referenced index */
1478
1479 dict_vcol_set* v_cols; /*!< set of virtual columns affected
1480 by foreign key constraint. */
1481
1482 /** Check whether the fulltext index gets affected by
1483 foreign key constraint */
1484 bool affects_fulltext() const;
1485 };
1486
1487 std::ostream&
1488 operator<< (std::ostream& out, const dict_foreign_t& foreign);
1489
1490 struct dict_foreign_print {
1491
1492 dict_foreign_print(std::ostream& out)
1493 : m_out(out)
1494 {}
1495
1496 void operator()(const dict_foreign_t* foreign) {
1497 m_out << *foreign;
1498 }
1499 private:
1500 std::ostream& m_out;
1501 };
1502
1503 /** Compare two dict_foreign_t objects using their ids. Used in the ordering
1504 of dict_table_t::foreign_set and dict_table_t::referenced_set. It returns
1505 true if the first argument is considered to go before the second in the
1506 strict weak ordering it defines, and false otherwise. */
1507 struct dict_foreign_compare {
1508
1509 bool operator()(
1510 const dict_foreign_t* lhs,
1511 const dict_foreign_t* rhs) const
1512 {
1513 return(ut_strcmp(lhs->id, rhs->id) < 0);
1514 }
1515 };
1516
1517 /** A function object to find a foreign key with the given index as the
1518 referenced index. Return the foreign key with matching criteria or NULL */
1519 struct dict_foreign_with_index {
1520
1521 dict_foreign_with_index(const dict_index_t* index)
1522 : m_index(index)
1523 {}
1524
1525 bool operator()(const dict_foreign_t* foreign) const
1526 {
1527 return(foreign->referenced_index == m_index);
1528 }
1529
1530 const dict_index_t* m_index;
1531 };
1532
1533 #ifdef WITH_WSREP
1534 /** A function object to find a foreign key with the given index as the
1535 foreign index. Return the foreign key with matching criteria or NULL */
1536 struct dict_foreign_with_foreign_index {
1537
1538 dict_foreign_with_foreign_index(const dict_index_t* index)
1539 : m_index(index)
1540 {}
1541
1542 bool operator()(const dict_foreign_t* foreign) const
1543 {
1544 return(foreign->foreign_index == m_index);
1545 }
1546
1547 const dict_index_t* m_index;
1548 };
1549 #endif
1550
1551 /* A function object to check if the foreign constraint is between different
1552 tables. Returns true if foreign key constraint is between different tables,
1553 false otherwise. */
1554 struct dict_foreign_different_tables {
1555
1556 bool operator()(const dict_foreign_t* foreign) const
1557 {
1558 return(foreign->foreign_table != foreign->referenced_table);
1559 }
1560 };
1561
1562 /** A function object to check if the foreign key constraint has the same
1563 name as given. If the full name of the foreign key constraint doesn't match,
1564 then, check if removing the database name from the foreign key constraint
1565 matches. Return true if it matches, false otherwise. */
1566 struct dict_foreign_matches_id {
1567
1568 dict_foreign_matches_id(const char* id)
1569 : m_id(id)
1570 {}
1571
1572 bool operator()(const dict_foreign_t* foreign) const
1573 {
1574 if (0 == innobase_strcasecmp(foreign->id, m_id)) {
1575 return(true);
1576 }
1577 if (const char* pos = strchr(foreign->id, '/')) {
1578 if (0 == innobase_strcasecmp(m_id, pos + 1)) {
1579 return(true);
1580 }
1581 }
1582 return(false);
1583 }
1584
1585 const char* m_id;
1586 };
1587
1588 typedef std::set<
1589 dict_foreign_t*,
1590 dict_foreign_compare,
1591 ut_allocator<dict_foreign_t*> > dict_foreign_set;
1592
1593 std::ostream&
1594 operator<< (std::ostream& out, const dict_foreign_set& fk_set);
1595
1596 /** Function object to check if a foreign key object is there
1597 in the given foreign key set or not. It returns true if the
1598 foreign key is not found, false otherwise */
1599 struct dict_foreign_not_exists {
1600 dict_foreign_not_exists(const dict_foreign_set& obj_)
1601 : m_foreigns(obj_)
1602 {}
1603
1604 /* Return true if the given foreign key is not found */
1605 bool operator()(dict_foreign_t* const & foreign) const {
1606 return(m_foreigns.find(foreign) == m_foreigns.end());
1607 }
1608 private:
1609 const dict_foreign_set& m_foreigns;
1610 };
1611
1612 /** Validate the search order in the foreign key set.
1613 @param[in] fk_set the foreign key set to be validated
1614 @return true if search order is fine in the set, false otherwise. */
1615 bool
1616 dict_foreign_set_validate(
1617 const dict_foreign_set& fk_set);
1618
1619 /** Validate the search order in the foreign key sets of the table
1620 (foreign_set and referenced_set).
1621 @param[in] table table whose foreign key sets are to be validated
1622 @return true if foreign key sets are fine, false otherwise. */
1623 bool
1624 dict_foreign_set_validate(
1625 const dict_table_t& table);
1626
1627 /*********************************************************************//**
1628 Frees a foreign key struct. */
1629 inline
1630 void
1631 dict_foreign_free(
1632 /*==============*/
1633 dict_foreign_t* foreign) /*!< in, own: foreign key struct */
1634 {
1635 if (foreign->v_cols != NULL) {
1636 UT_DELETE(foreign->v_cols);
1637 }
1638
1639 mem_heap_free(foreign->heap);
1640 }
1641
1642 /** The destructor will free all the foreign key constraints in the set
1643 by calling dict_foreign_free() on each of the foreign key constraints.
1644 This is used to free the allocated memory when a local set goes out
1645 of scope. */
1646 struct dict_foreign_set_free {
1647
1648 dict_foreign_set_free(const dict_foreign_set& foreign_set)
1649 : m_foreign_set(foreign_set)
1650 {}
1651
1652 ~dict_foreign_set_free()
1653 {
1654 std::for_each(m_foreign_set.begin(),
1655 m_foreign_set.end(),
1656 dict_foreign_free);
1657 }
1658
1659 const dict_foreign_set& m_foreign_set;
1660 };
1661
1662 /** The flags for ON_UPDATE and ON_DELETE can be ORed; the default is that
1663 a foreign key constraint is enforced, therefore RESTRICT just means no flag */
1664 /* @{ */
1665 #define DICT_FOREIGN_ON_DELETE_CASCADE 1U /*!< ON DELETE CASCADE */
1666 #define DICT_FOREIGN_ON_DELETE_SET_NULL 2U /*!< ON UPDATE SET NULL */
1667 #define DICT_FOREIGN_ON_UPDATE_CASCADE 4U /*!< ON DELETE CASCADE */
1668 #define DICT_FOREIGN_ON_UPDATE_SET_NULL 8U /*!< ON UPDATE SET NULL */
1669 #define DICT_FOREIGN_ON_DELETE_NO_ACTION 16U /*!< ON DELETE NO ACTION */
1670 #define DICT_FOREIGN_ON_UPDATE_NO_ACTION 32U /*!< ON UPDATE NO ACTION */
1671 /* @} */
1672
1673 /** Display an identifier.
1674 @param[in,out] s output stream
1675 @param[in] id_name SQL identifier (other than table name)
1676 @return the output stream */
1677 std::ostream&
1678 operator<<(
1679 std::ostream& s,
1680 const id_name_t& id_name);
1681
1682 /** Display a table name.
1683 @param[in,out] s output stream
1684 @param[in] table_name table name
1685 @return the output stream */
1686 std::ostream&
1687 operator<<(
1688 std::ostream& s,
1689 const table_name_t& table_name);
1690
1691 /** List of locks that different transactions have acquired on a table. This
1692 list has a list node that is embedded in a nested union/structure. We have to
1693 generate a specific template for it. */
1694
1695 typedef ut_list_base<lock_t, ut_list_node<lock_t> lock_table_t::*>
1696 table_lock_list_t;
1697
1698 /** mysql template structure defined in row0mysql.cc */
1699 struct mysql_row_templ_t;
1700
1701 /** Structure defines template related to virtual columns and
1702 their base columns */
1703 struct dict_vcol_templ_t {
1704 /** number of regular columns */
1705 ulint n_col;
1706
1707 /** number of virtual columns */
1708 ulint n_v_col;
1709
1710 /** array of templates for virtual col and their base columns */
1711 mysql_row_templ_t** vtempl;
1712
1713 /** table's database name */
1714 std::string db_name;
1715
1716 /** table name */
1717 std::string tb_name;
1718
1719 /** MySQL record length */
1720 ulint rec_len;
1721
1722 /** default column value if any */
1723 byte* default_rec;
1724
1725 /** cached MySQL TABLE object */
1726 TABLE* mysql_table;
1727
1728 /** when mysql_table was cached */
1729 uint64_t mysql_table_query_id;
1730
1731 dict_vcol_templ_t() : vtempl(0), mysql_table_query_id(~0ULL) {}
1732 };
1733
1734 /** Metadata on clustered index fields starting from first_user_field() */
1735 class field_map_element_t
1736 {
1737 /** Number of bits for representing a column number */
1738 static constexpr uint16_t IND_BITS = 10;
1739
1740 /** Set if the column of the field has been instantly dropped */
1741 static constexpr uint16_t DROPPED = 1U << (IND_BITS + 5);
1742
1743 /** Set if the column was dropped and originally declared NOT NULL */
1744 static constexpr uint16_t NOT_NULL = 1U << (IND_BITS + 4);
1745
1746 /** Column index (if !(data & DROPPED)): table->cols[data & IND],
1747 or field length (if (data & DROPPED)):
1748 (data & IND) = 0 if variable-length with max_len < 256 bytes;
1749 (data & IND) = 1 if variable-length with max_len > 255 bytes;
1750 (data & IND) = 1 + L otherwise, with L=fixed length of the column */
1751 static constexpr uint16_t IND = (1U << IND_BITS) - 1;
1752
1753 /** Field metadata */
1754 uint16_t data;
1755
1756 void clear_not_null() { data &= ~NOT_NULL; }
1757 public:
1758 bool is_dropped() const { return data & DROPPED; }
1759 void set_dropped() { data |= DROPPED; }
1760 bool is_not_null() const { return data & NOT_NULL; }
1761 void set_not_null() { ut_ad(is_dropped()); data |= NOT_NULL; }
1762 uint16_t ind() const { return data & IND; }
1763 void set_ind(uint16_t i)
1764 {
1765 DBUG_ASSERT(i <= IND);
1766 DBUG_ASSERT(!ind());
1767 data |= i;
1768 }
1769 field_map_element_t& operator= (uint16_t value)
1770 {
1771 data = value;
1772 return *this;
1773 }
1774 operator uint16_t() { return data; }
1775 };
1776
1777 static_assert(sizeof(field_map_element_t) == 2,
1778 "Size mismatch for a persistent data item!");
1779
1780 /** Instantly dropped or reordered columns */
1781 struct dict_instant_t
1782 {
1783 /** Number of dropped columns */
1784 unsigned n_dropped;
1785 /** Dropped columns */
1786 dict_col_t* dropped;
1787 /** Map of clustered index non-PK fields[i - first_user_field()]
1788 to table columns */
1789 field_map_element_t* field_map;
1790 };
1791
1792 /** These are used when MySQL FRM and InnoDB data dictionary are
1793 in inconsistent state. */
1794 typedef enum {
1795 DICT_FRM_CONSISTENT = 0, /*!< Consistent state */
1796 DICT_FRM_NO_PK = 1, /*!< MySQL has no primary key
1797 but InnoDB dictionary has
1798 non-generated one. */
1799 DICT_NO_PK_FRM_HAS = 2, /*!< MySQL has primary key but
1800 InnoDB dictionary has not. */
1801 DICT_FRM_INCONSISTENT_KEYS = 3 /*!< Key count mismatch */
1802 } dict_frm_t;
1803
1804 /** Data structure for a database table. Most fields will be
1805 initialized to 0, NULL or FALSE in dict_mem_table_create(). */
1806 struct dict_table_t {
1807
1808 /** Get reference count.
1809 @return current value of n_ref_count */
1810 inline uint32_t get_ref_count() const { return n_ref_count; }
1811
1812 /** Acquire the table handle. */
1813 inline void acquire();
1814
1815 /** Release the table handle.
1816 @return whether the last handle was released */
1817 inline bool release();
1818
1819 /** @return whether the table supports transactions */
1820 bool no_rollback() const
1821 {
1822 return !(~unsigned(flags) & DICT_TF_MASK_NO_ROLLBACK);
1823 }
1824 /** @return whether this is a temporary table */
1825 bool is_temporary() const
1826 {
1827 return flags2 & DICT_TF2_TEMPORARY;
1828 }
1829
1830 /** @return whether the table is not in ROW_FORMAT=REDUNDANT */
1831 bool not_redundant() const { return flags & DICT_TF_COMPACT; }
1832
1833 /** @return whether this table is readable
1834 @retval true normally
1835 @retval false if this is a single-table tablespace
1836 and the .ibd file is missing, or a
1837 page cannot be read or decrypted */
1838 bool is_readable() const
1839 {
1840 ut_ad(file_unreadable || space);
1841 return(UNIV_LIKELY(!file_unreadable));
1842 }
1843
1844 /** Check if a table name contains the string "/#sql"
1845 which denotes temporary or intermediate tables in MariaDB. */
1846 static bool is_temporary_name(const char* name)
1847 {
1848 return strstr(name, "/" TEMP_FILE_PREFIX) != NULL;
1849 }
1850
1851 /** @return whether instant ALTER TABLE is in effect */
1852 bool is_instant() const
1853 {
1854 return(UT_LIST_GET_FIRST(indexes)->is_instant());
1855 }
1856
1857 /** @return whether the table supports instant ALTER TABLE */
1858 bool supports_instant() const
1859 {
1860 return(!(flags & DICT_TF_MASK_ZIP_SSIZE));
1861 }
1862
1863 /** @return the number of instantly dropped columns */
1864 unsigned n_dropped() const { return instant ? instant->n_dropped : 0; }
1865
1866 /** Look up an old column.
1867 @param[in] cols the old columns of the table
1868 @param[in] col_map map from old table columns to altered ones
1869 @param[in] n_cols number of old columns
1870 @param[in] i the number of the new column
1871 @return old column
1872 @retval NULL if column i was added to the table */
1873 static const dict_col_t* find(const dict_col_t* cols,
1874 const ulint* col_map, ulint n_cols,
1875 ulint i)
1876 {
1877 for (ulint o = n_cols; o--; ) {
1878 if (col_map[o] == i) {
1879 return &cols[o];
1880 }
1881 }
1882 return NULL;
1883 }
1884
1885 /** Serialise metadata of dropped or reordered columns.
1886 @param[in,out] heap memory heap for allocation
1887 @param[out] field data field with the metadata */
1888 inline void serialise_columns(mem_heap_t* heap, dfield_t* field) const;
1889
1890 /** Reconstruct dropped or reordered columns.
1891 @param[in] metadata data from serialise_columns()
1892 @param[in] len length of the metadata, in bytes
1893 @return whether parsing the metadata failed */
1894 bool deserialise_columns(const byte* metadata, ulint len);
1895
1896 /** Set is_instant() before instant_column().
1897 @param[in] old previous table definition
1898 @param[in] col_map map from old.cols[]
1899 and old.v_cols[] to this
1900 @param[out] first_alter_pos 0, or
1901 1 + first changed column position */
1902 inline void prepare_instant(const dict_table_t& old,
1903 const ulint* col_map,
1904 unsigned& first_alter_pos);
1905
1906 /** Adjust table metadata for instant ADD/DROP/reorder COLUMN.
1907 @param[in] table table on which prepare_instant() was invoked
1908 @param[in] col_map mapping from cols[] and v_cols[] to table
1909 @return whether the metadata record must be updated */
1910 inline bool instant_column(const dict_table_t& table,
1911 const ulint* col_map);
1912
1913 /** Roll back instant_column().
1914 @param[in] old_n_cols original n_cols
1915 @param[in] old_cols original cols
1916 @param[in] old_col_names original col_names
1917 @param[in] old_instant original instant structure
1918 @param[in] old_fields original fields
1919 @param[in] old_n_fields original number of fields
1920 @param[in] old_n_core_fields original number of core fields
1921 @param[in] old_n_v_cols original n_v_cols
1922 @param[in] old_v_cols original v_cols
1923 @param[in] old_v_col_names original v_col_names
1924 @param[in] col_map column map */
1925 inline void rollback_instant(
1926 unsigned old_n_cols,
1927 dict_col_t* old_cols,
1928 const char* old_col_names,
1929 dict_instant_t* old_instant,
1930 dict_field_t* old_fields,
1931 unsigned old_n_fields,
1932 unsigned old_n_core_fields,
1933 unsigned old_n_v_cols,
1934 dict_v_col_t* old_v_cols,
1935 const char* old_v_col_names,
1936 const ulint* col_map);
1937
1938 /** Add the table definition to the data dictionary cache */
1939 void add_to_cache();
1940
1941 /** @return whether the table is versioned.
1942 It is assumed that both vers_start and vers_end set to 0
1943 iff table is not versioned. In any other case,
1944 these fields correspond to actual positions in cols[]. */
1945 bool versioned() const { return vers_start || vers_end; }
1946 bool versioned_by_id() const
1947 {
1948 return versioned() && cols[vers_start].mtype == DATA_INT;
1949 }
1950
1951 void inc_fk_checks()
1952 {
1953 #ifdef UNIV_DEBUG
1954 int32_t fk_checks=
1955 #endif
1956 n_foreign_key_checks_running++;
1957 ut_ad(fk_checks >= 0);
1958 }
1959 void dec_fk_checks()
1960 {
1961 #ifdef UNIV_DEBUG
1962 int32_t fk_checks=
1963 #endif
1964 n_foreign_key_checks_running--;
1965 ut_ad(fk_checks > 0);
1966 }
1967
1968 /** For overflow fields returns potential max length stored inline */
1969 inline size_t get_overflow_field_local_len() const;
1970
1971 private:
1972 /** Initialize instant->field_map.
1973 @param[in] table table definition to copy from */
1974 inline void init_instant(const dict_table_t& table);
1975 public:
1976 /** Id of the table. */
1977 table_id_t id;
1978 /** Hash chain node. */
1979 hash_node_t id_hash;
1980 /** Table name. */
1981 table_name_t name;
1982 /** Hash chain node. */
1983 hash_node_t name_hash;
1984
1985 /** Memory heap */
1986 mem_heap_t* heap;
1987
1988 /** NULL or the directory path specified by DATA DIRECTORY. */
1989 char* data_dir_path;
1990
1991 /** The tablespace of the table */
1992 fil_space_t* space;
1993 /** Tablespace ID */
1994 ulint space_id;
1995
1996 /** Stores information about:
1997 1 row format (redundant or compact),
1998 2 compressed page size (zip shift size),
1999 3 whether using atomic blobs,
2000 4 whether the table has been created with the option DATA DIRECTORY.
2001 Use DICT_TF_GET_COMPACT(), DICT_TF_GET_ZIP_SSIZE(),
2002 DICT_TF_HAS_ATOMIC_BLOBS() and DICT_TF_HAS_DATA_DIR() to parse this
2003 flag. */
2004 unsigned flags:DICT_TF_BITS;
2005
2006 /** Stores information about:
2007 1 whether the table has been created using CREATE TEMPORARY TABLE,
2008 2 whether the table has an internally defined DOC ID column,
2009 3 whether the table has a FTS index,
2010 4 whether DOC ID column need to be added to the FTS index,
2011 5 whether the table is being created its own tablespace,
2012 6 whether the table has been DISCARDed,
2013 7 whether the aux FTS tables names are in hex.
2014 Use DICT_TF2_FLAG_IS_SET() to parse this flag. */
2015 unsigned flags2:DICT_TF2_BITS;
2016
2017 /** TRUE if the table is an intermediate table during copy alter
2018 operation or a partition/subpartition which is required for copying
2019 data and skip the undo log for insertion of row in the table.
2020 This variable will be set and unset during extra(), or during the
2021 process of altering partitions */
2022 unsigned skip_alter_undo:1;
2023
2024 /*!< whether this is in a single-table tablespace and the .ibd
2025 file is missing or page decryption failed and page is corrupted */
2026 unsigned file_unreadable:1;
2027
2028 /** TRUE if the table object has been added to the dictionary cache. */
2029 unsigned cached:1;
2030
2031 /** TRUE if the table is to be dropped, but not yet actually dropped
2032 (could in the background drop list). It is turned on at the beginning
2033 of row_drop_table_for_mysql() and turned off just before we start to
2034 update system tables for the drop. It is protected by dict_sys.latch. */
2035 unsigned to_be_dropped:1;
2036
2037 /** Number of non-virtual columns defined so far. */
2038 unsigned n_def:10;
2039
2040 /** Number of non-virtual columns. */
2041 unsigned n_cols:10;
2042
2043 /** Number of total columns (inlcude virtual and non-virtual) */
2044 unsigned n_t_cols:10;
2045
2046 /** Number of total columns defined so far. */
2047 unsigned n_t_def:10;
2048
2049 /** Number of virtual columns defined so far. */
2050 unsigned n_v_def:10;
2051
2052 /** Number of virtual columns. */
2053 unsigned n_v_cols:10;
2054
2055 /** 1 + the position of autoinc counter field in clustered
2056 index, or 0 if there is no persistent AUTO_INCREMENT column in
2057 the table. */
2058 unsigned persistent_autoinc:10;
2059
2060 /** TRUE if it's not an InnoDB system table or a table that has no FK
2061 relationships. */
2062 unsigned can_be_evicted:1;
2063
2064 /** TRUE if table is corrupted. */
2065 unsigned corrupted:1;
2066
2067 /** TRUE if some indexes should be dropped after ONLINE_INDEX_ABORTED
2068 or ONLINE_INDEX_ABORTED_DROPPED. */
2069 unsigned drop_aborted:1;
2070
2071 /** Array of column descriptions. */
2072 dict_col_t* cols;
2073
2074 /** Array of virtual column descriptions. */
2075 dict_v_col_t* v_cols;
2076
2077 /** List of stored column descriptions. It is used only for foreign key
2078 check during create table and copy alter operations.
2079 During copy alter, s_cols list is filled during create table operation
2080 and need to preserve till rename table operation. That is the
2081 reason s_cols is a part of dict_table_t */
2082 dict_s_col_list* s_cols;
2083
2084 /** Instantly dropped or reordered columns, or NULL if none */
2085 dict_instant_t* instant;
2086
2087 /** Column names packed in a character string
2088 "name1\0name2\0...nameN\0". Until the string contains n_cols, it will
2089 be allocated from a temporary heap. The final string will be allocated
2090 from table->heap. */
2091 const char* col_names;
2092
2093 /** Virtual column names */
2094 const char* v_col_names;
2095 unsigned vers_start:10;
2096 /*!< System Versioning: row start col index */
2097 unsigned vers_end:10;
2098 /*!< System Versioning: row end col index */
2099 bool is_system_db;
2100 /*!< True if the table belongs to a system
2101 database (mysql, information_schema or
2102 performance_schema) */
2103 dict_frm_t dict_frm_mismatch;
2104 /*!< !DICT_FRM_CONSISTENT==0 if data
2105 dictionary information and
2106 MySQL FRM information mismatch. */
2107 /** The FTS_DOC_ID_INDEX, or NULL if no fulltext indexes exist */
2108 dict_index_t* fts_doc_id_index;
2109
2110 /** List of indexes of the table. */
2111 UT_LIST_BASE_NODE_T(dict_index_t) indexes;
2112 #ifdef BTR_CUR_HASH_ADAPT
2113 /** List of detached indexes that are waiting to be freed along with
2114 the last adaptive hash index entry.
2115 Protected by autoinc_mutex (sic!) */
2116 UT_LIST_BASE_NODE_T(dict_index_t) freed_indexes;
2117 #endif /* BTR_CUR_HASH_ADAPT */
2118
2119 /** List of foreign key constraints in the table. These refer to
2120 columns in other tables. */
2121 UT_LIST_BASE_NODE_T(dict_foreign_t) foreign_list;
2122
2123 /** List of foreign key constraints which refer to this table. */
2124 UT_LIST_BASE_NODE_T(dict_foreign_t) referenced_list;
2125
2126 /** Node of the LRU list of tables. */
2127 UT_LIST_NODE_T(dict_table_t) table_LRU;
2128
2129 /** Maximum recursive level we support when loading tables chained
2130 together with FK constraints. If exceeds this level, we will stop
2131 loading child table into memory along with its parent table. */
2132 unsigned fk_max_recusive_level:8;
2133
2134 /** Count of how many foreign key check operations are currently being
2135 performed on the table. We cannot drop the table while there are
2136 foreign key checks running on it. */
2137 Atomic_counter<int32_t> n_foreign_key_checks_running;
2138
2139 /** Transactions whose view low limit is greater than this number are
2140 not allowed to store to the MySQL query cache or retrieve from it.
2141 When a trx with undo logs commits, it sets this to the value of the
2142 transaction id. */
2143 trx_id_t query_cache_inv_trx_id;
2144
2145 /** Transaction id that last touched the table definition. Either when
2146 loading the definition or CREATE TABLE, or ALTER TABLE (prepare,
2147 commit, and rollback phases). */
2148 trx_id_t def_trx_id;
2149
2150 /*!< set of foreign key constraints in the table; these refer to
2151 columns in other tables */
2152 dict_foreign_set foreign_set;
2153
2154 /*!< set of foreign key constraints which refer to this table */
2155 dict_foreign_set referenced_set;
2156
2157 /** Statistics for query optimization. Mostly protected by
2158 dict_sys.mutex. @{ */
2159
2160 /** TRUE if statistics have been calculated the first time after
2161 database startup or table creation. */
2162 unsigned stat_initialized:1;
2163
2164 /** Timestamp of last recalc of the stats. */
2165 time_t stats_last_recalc;
2166
2167 /** The two bits below are set in the 'stat_persistent' member. They
2168 have the following meaning:
2169 1. _ON=0, _OFF=0, no explicit persistent stats setting for this table,
2170 the value of the global srv_stats_persistent is used to determine
2171 whether the table has persistent stats enabled or not
2172 2. _ON=0, _OFF=1, persistent stats are explicitly disabled for this
2173 table, regardless of the value of the global srv_stats_persistent
2174 3. _ON=1, _OFF=0, persistent stats are explicitly enabled for this
2175 table, regardless of the value of the global srv_stats_persistent
2176 4. _ON=1, _OFF=1, not allowed, we assert if this ever happens. */
2177 #define DICT_STATS_PERSISTENT_ON (1 << 1)
2178 #define DICT_STATS_PERSISTENT_OFF (1 << 2)
2179
2180 /** Indicates whether the table uses persistent stats or not. See
2181 DICT_STATS_PERSISTENT_ON and DICT_STATS_PERSISTENT_OFF. */
2182 ib_uint32_t stat_persistent;
2183
2184 /** The two bits below are set in the 'stats_auto_recalc' member. They
2185 have the following meaning:
2186 1. _ON=0, _OFF=0, no explicit auto recalc setting for this table, the
2187 value of the global srv_stats_persistent_auto_recalc is used to
2188 determine whether the table has auto recalc enabled or not
2189 2. _ON=0, _OFF=1, auto recalc is explicitly disabled for this table,
2190 regardless of the value of the global srv_stats_persistent_auto_recalc
2191 3. _ON=1, _OFF=0, auto recalc is explicitly enabled for this table,
2192 regardless of the value of the global srv_stats_persistent_auto_recalc
2193 4. _ON=1, _OFF=1, not allowed, we assert if this ever happens. */
2194 #define DICT_STATS_AUTO_RECALC_ON (1 << 1)
2195 #define DICT_STATS_AUTO_RECALC_OFF (1 << 2)
2196
2197 /** Indicates whether the table uses automatic recalc for persistent
2198 stats or not. See DICT_STATS_AUTO_RECALC_ON and
2199 DICT_STATS_AUTO_RECALC_OFF. */
2200 ib_uint32_t stats_auto_recalc;
2201
2202 /** The number of pages to sample for this table during persistent
2203 stats estimation. If this is 0, then the value of the global
2204 srv_stats_persistent_sample_pages will be used instead. */
2205 ulint stats_sample_pages;
2206
2207 /** Approximate number of rows in the table. We periodically calculate
2208 new estimates. */
2209 ib_uint64_t stat_n_rows;
2210
2211 /** Approximate clustered index size in database pages. */
2212 ulint stat_clustered_index_size;
2213
2214 /** Approximate size of other indexes in database pages. */
2215 ulint stat_sum_of_other_index_sizes;
2216
2217 /** How many rows are modified since last stats recalc. When a row is
2218 inserted, updated, or deleted, we add 1 to this number; we calculate
2219 new estimates for the table and the indexes if the table has changed
2220 too much, see dict_stats_update_if_needed(). The counter is reset
2221 to zero at statistics calculation. This counter is not protected by
2222 any latch, because this is only used for heuristics. */
2223 ib_uint64_t stat_modified_counter;
2224
2225 /** Background stats thread is not working on this table. */
2226 #define BG_STAT_NONE 0
2227
2228 /** Set in 'stats_bg_flag' when the background stats code is working
2229 on this table. The DROP TABLE code waits for this to be cleared before
2230 proceeding. */
2231 #define BG_STAT_IN_PROGRESS (1 << 0)
2232
2233 /** Set in 'stats_bg_flag' when DROP TABLE starts waiting on
2234 BG_STAT_IN_PROGRESS to be cleared. The background stats thread will
2235 detect this and will eventually quit sooner. */
2236 #define BG_STAT_SHOULD_QUIT (1 << 1)
2237
2238 /** The state of the background stats thread wrt this table.
2239 See BG_STAT_NONE, BG_STAT_IN_PROGRESS and BG_STAT_SHOULD_QUIT.
2240 Writes are covered by dict_sys.mutex. Dirty reads are possible. */
2241
2242 #define BG_SCRUB_IN_PROGRESS ((byte)(1 << 2))
2243 /*!< BG_SCRUB_IN_PROGRESS is set in
2244 stats_bg_flag when the background
2245 scrub code is working on this table. The DROP
2246 TABLE code waits for this to be cleared
2247 before proceeding. */
2248
2249 #define BG_STAT_SHOULD_QUIT (1 << 1)
2250
2251 #define BG_IN_PROGRESS (BG_STAT_IN_PROGRESS | BG_SCRUB_IN_PROGRESS)
2252
2253
2254 /** The state of the background stats thread wrt this table.
2255 See BG_STAT_NONE, BG_STAT_IN_PROGRESS and BG_STAT_SHOULD_QUIT.
2256 Writes are covered by dict_sys.mutex. Dirty reads are possible. */
2257 byte stats_bg_flag;
2258
2259 bool stats_error_printed;
2260 /*!< Has persistent stats error beein
2261 already printed for this table ? */
2262 /* @} */
2263
2264 /** AUTOINC related members. @{ */
2265
2266 /* The actual collection of tables locked during AUTOINC read/write is
2267 kept in trx_t. In order to quickly determine whether a transaction has
2268 locked the AUTOINC lock we keep a pointer to the transaction here in
2269 the 'autoinc_trx' member. This is to avoid acquiring the
2270 lock_sys_t::mutex and scanning the vector in trx_t.
2271 When an AUTOINC lock has to wait, the corresponding lock instance is
2272 created on the trx lock heap rather than use the pre-allocated instance
2273 in autoinc_lock below. */
2274
2275 /** A buffer for an AUTOINC lock for this table. We allocate the
2276 memory here so that individual transactions can get it and release it
2277 without a need to allocate space from the lock heap of the trx:
2278 otherwise the lock heap would grow rapidly if we do a large insert
2279 from a select. */
2280 lock_t* autoinc_lock;
2281
2282 /** Mutex protecting the autoinc counter and freed_indexes. */
2283 std::mutex autoinc_mutex;
2284
2285 /** Autoinc counter value to give to the next inserted row. */
2286 ib_uint64_t autoinc;
2287
2288 /** This counter is used to track the number of granted and pending
2289 autoinc locks on this table. This value is set after acquiring the
2290 lock_sys_t::mutex but we peek the contents to determine whether other
2291 transactions have acquired the AUTOINC lock or not. Of course only one
2292 transaction can be granted the lock but there can be multiple
2293 waiters. */
2294 ulong n_waiting_or_granted_auto_inc_locks;
2295
2296 /** The transaction that currently holds the the AUTOINC lock on this
2297 table. Protected by lock_sys.mutex. */
2298 const trx_t* autoinc_trx;
2299
2300 /* @} */
2301
2302 /** FTS specific state variables. */
2303 fts_t* fts;
2304
2305 /** Quiescing states, protected by the dict_index_t::lock. ie. we can
2306 only change the state if we acquire all the latches (dict_index_t::lock)
2307 in X mode of this table's indexes. */
2308 ib_quiesce_t quiesce;
2309
2310 /** Count of the number of record locks on this table. We use this to
2311 determine whether we can evict the table from the dictionary cache.
2312 It is protected by lock_sys.mutex. */
2313 ulint n_rec_locks;
2314 private:
2315 /** Count of how many handles are opened to this table. Dropping of the
2316 table is NOT allowed until this count gets to zero. MySQL does NOT
2317 itself check the number of open handles at DROP. */
2318 Atomic_counter<uint32_t> n_ref_count;
2319
2320 public:
2321 /** List of locks on the table. Protected by lock_sys.mutex. */
2322 table_lock_list_t locks;
2323
2324 /** Timestamp of the last modification of this table. */
2325 time_t update_time;
2326
2327 #ifdef UNIV_DEBUG
2328 /** Value of 'magic_n'. */
2329 #define DICT_TABLE_MAGIC_N 76333786
2330
2331 /** Magic number. */
2332 ulint magic_n;
2333 #endif /* UNIV_DEBUG */
2334 /** mysql_row_templ_t for base columns used for compute the virtual
2335 columns */
2336 dict_vcol_templ_t* vc_templ;
2337
2338 /* @return whether the table has any other transcation lock
2339 other than the given transaction */
2340 bool has_lock_other_than(const trx_t *trx) const
2341 {
2342 for (lock_t *lock= UT_LIST_GET_FIRST(locks); lock;
2343 lock= UT_LIST_GET_NEXT(un_member.tab_lock.locks, lock))
2344 if (lock->trx != trx)
2345 return true;
2346 return false;
2347 }
2348
2349 /** Check whether the table name is same as mysql/innodb_stats_table
2350 or mysql/innodb_index_stats.
2351 @return true if the table name is same as stats table */
2352 bool is_stats_table() const;
2353 };
2354
2355 inline void dict_index_t::set_modified(mtr_t& mtr) const
2356 {
2357 mtr.set_named_space(table->space);
2358 }
2359
2360 inline bool table_name_t::is_temporary() const
2361 {
2362 return dict_table_t::is_temporary_name(m_name);
2363 }
2364
2365 inline bool dict_index_t::is_readable() const { return table->is_readable(); }
2366
2367 inline bool dict_index_t::is_instant() const
2368 {
2369 ut_ad(n_core_fields > 0);
2370 ut_ad(n_core_fields <= n_fields || table->n_dropped());
2371 ut_ad(n_core_fields == n_fields
2372 || (type & ~(DICT_UNIQUE | DICT_CORRUPT)) == DICT_CLUSTERED);
2373 ut_ad(n_core_fields == n_fields || table->supports_instant());
2374 ut_ad(n_core_fields == n_fields || !table->is_temporary());
2375 ut_ad(!table->instant || !table->is_temporary());
2376
2377 return n_core_fields != n_fields
2378 || (is_primary() && table->instant);
2379 }
2380
2381 inline bool dict_index_t::is_corrupted() const
2382 {
2383 return UNIV_UNLIKELY(online_status >= ONLINE_INDEX_ABORTED
2384 || (type & DICT_CORRUPT)
2385 || (table && table->corrupted));
2386 }
2387
2388 inline void dict_index_t::clear_instant_add()
2389 {
2390 DBUG_ASSERT(is_primary());
2391 DBUG_ASSERT(is_instant());
2392 DBUG_ASSERT(!table->instant);
2393 for (unsigned i = n_core_fields; i < n_fields; i++) {
2394 fields[i].col->clear_instant();
2395 }
2396 n_core_fields = n_fields;
2397 n_core_null_bytes = UT_BITS_IN_BYTES(unsigned(n_nullable));
2398 }
2399
2400 inline void dict_index_t::clear_instant_alter()
2401 {
2402 DBUG_ASSERT(is_primary());
2403 DBUG_ASSERT(n_fields == n_def);
2404
2405 if (!table->instant) {
2406 if (is_instant()) {
2407 clear_instant_add();
2408 }
2409 return;
2410 }
2411
2412 #ifndef DBUG_OFF
2413 for (unsigned i = first_user_field(); i--; ) {
2414 DBUG_ASSERT(!fields[i].col->is_dropped());
2415 DBUG_ASSERT(!fields[i].col->is_nullable());
2416 }
2417 #endif
2418 const dict_col_t* ai_col = table->persistent_autoinc
2419 ? fields[table->persistent_autoinc - 1].col
2420 : NULL;
2421 dict_field_t* const begin = &fields[first_user_field()];
2422 dict_field_t* end = &fields[n_fields];
2423
2424 for (dict_field_t* d = begin; d < end; ) {
2425 /* Move fields for dropped columns to the end. */
2426 if (!d->col->is_dropped()) {
2427 d++;
2428 } else {
2429 if (d->col->is_nullable()) {
2430 n_nullable--;
2431 }
2432
2433 std::swap(*d, *--end);
2434 }
2435 }
2436
2437 DBUG_ASSERT(&fields[n_fields - table->n_dropped()] == end);
2438 n_core_fields = n_fields = n_def = end - fields;
2439 n_core_null_bytes = UT_BITS_IN_BYTES(n_nullable);
2440 std::sort(begin, end, [](const dict_field_t& a, const dict_field_t& b)
2441 { return a.col->ind < b.col->ind; });
2442 table->instant = NULL;
2443 if (ai_col) {
2444 auto a = std::find_if(fields, end,
2445 [ai_col](const dict_field_t& f)
2446 { return f.col == ai_col; });
2447 table->persistent_autoinc = (a == end) ? 0 : 1 + (a - fields);
2448 }
2449 }
2450
2451 /** @return whether the column was instantly dropped
2452 @param[in] index the clustered index */
2453 inline bool dict_col_t::is_dropped(const dict_index_t& index) const
2454 {
2455 DBUG_ASSERT(index.is_primary());
2456 DBUG_ASSERT(!is_dropped() == !index.table->instant);
2457 DBUG_ASSERT(!is_dropped() || (this >= index.table->instant->dropped
2458 && this < index.table->instant->dropped
2459 + index.table->instant->n_dropped));
2460 return is_dropped();
2461 }
2462
2463 /*******************************************************************//**
2464 Initialise the table lock list. */
2465 void
2466 lock_table_lock_list_init(
2467 /*======================*/
2468 table_lock_list_t* locks); /*!< List to initialise */
2469
2470 /** A function object to add the foreign key constraint to the referenced set
2471 of the referenced table, if it exists in the dictionary cache. */
2472 struct dict_foreign_add_to_referenced_table {
2473 void operator()(dict_foreign_t* foreign) const
2474 {
2475 if (dict_table_t* table = foreign->referenced_table) {
2476 std::pair<dict_foreign_set::iterator, bool> ret
2477 = table->referenced_set.insert(foreign);
2478 ut_a(ret.second);
2479 }
2480 }
2481 };
2482
2483 /** Check whether the col is used in spatial index or regular index.
2484 @param[in] col column to check
2485 @return spatial status */
2486 inline
2487 spatial_status_t
2488 dict_col_get_spatial_status(
2489 const dict_col_t* col)
2490 {
2491 spatial_status_t spatial_status = SPATIAL_NONE;
2492
2493 /* Column is not a part of any index. */
2494 if (!col->ord_part) {
2495 return(spatial_status);
2496 }
2497
2498 if (DATA_GEOMETRY_MTYPE(col->mtype)) {
2499 if (col->max_prefix == 0) {
2500 spatial_status = SPATIAL_ONLY;
2501 } else {
2502 /* Any regular index on a geometry column
2503 should have a prefix. */
2504 spatial_status = SPATIAL_MIXED;
2505 }
2506 }
2507
2508 return(spatial_status);
2509 }
2510
2511 /** Clear defragmentation summary. */
2512 inline void dict_stats_empty_defrag_summary(dict_index_t* index)
2513 {
2514 index->stat_defrag_n_pages_freed = 0;
2515 }
2516
2517 /** Clear defragmentation related index stats. */
2518 inline void dict_stats_empty_defrag_stats(dict_index_t* index)
2519 {
2520 index->stat_defrag_modified_counter = 0;
2521 index->stat_defrag_n_page_split = 0;
2522 }
2523
2524 #include "dict0mem.inl"
2525
2526 #endif /* dict0mem_h */
2527