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