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