1 /*****************************************************************************
2 
3 Copyright (c) 1996, 2021, Oracle and/or its affiliates.
4 Copyright (c) 2012, Facebook Inc.
5 
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License, version 2.0,
8 as published by the Free Software Foundation.
9 
10 This program is also distributed with certain software (including
11 but not limited to OpenSSL) that is licensed under separate terms,
12 as designated in a particular file or component or in included license
13 documentation.  The authors of MySQL hereby grant you an additional
14 permission to link the program and your derivative works with the
15 separately licensed software that they have included with MySQL.
16 
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 GNU General Public License, version 2.0, for more details.
21 
22 You should have received a copy of the GNU General Public License along with
23 this program; if not, write to the Free Software Foundation, Inc.,
24 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
25 
26 *****************************************************************************/
27 
28 /**************************************************//**
29 @file include/dict0dict.h
30 Data dictionary system
31 
32 Created 1/8/1996 Heikki Tuuri
33 *******************************************************/
34 
35 #ifndef dict0dict_h
36 #define dict0dict_h
37 
38 #include "univ.i"
39 #include "data0data.h"
40 #include "data0type.h"
41 #include "dict0mem.h"
42 #include "dict0types.h"
43 #include "fsp0fsp.h"
44 #include "fsp0sysspace.h"
45 #include "hash0hash.h"
46 #include "mem0mem.h"
47 #include "rem0types.h"
48 #include "row0types.h"
49 #include "trx0types.h"
50 #include "trx0sys.h"
51 #include "ut0byte.h"
52 #include "ut0mem.h"
53 #include "ut0new.h"
54 #include "ut0rnd.h"
55 #include <deque>
56 
57 #ifndef UNIV_HOTBACKUP
58 # include "sync0rw.h"
59 /********************************************************************//**
60 Get the database name length in a table name.
61 @return database name length */
62 ulint
63 dict_get_db_name_len(
64 /*=================*/
65 	const char*	name)	/*!< in: table name in the form
66 				dbname '/' tablename */
67 	MY_ATTRIBUTE((warn_unused_result));
68 /*********************************************************************//**
69 Open a table from its database and table name, this is currently used by
70 foreign constraint parser to get the referenced table.
71 @return complete table name with database and table name, allocated from
72 heap memory passed in */
73 char*
74 dict_get_referenced_table(
75 /*======================*/
76 	const char*	name,		/*!< in: foreign key table name */
77 	const char*	database_name,	/*!< in: table db name */
78 	ulint		database_name_len,/*!< in: db name length */
79 	const char*	table_name,	/*!< in: table name */
80 	ulint		table_name_len,	/*!< in: table name length */
81 	dict_table_t**	table,		/*!< out: table object or NULL */
82 	mem_heap_t*	heap);		/*!< in: heap memory */
83 /*********************************************************************//**
84 Frees a foreign key struct. */
85 void
86 dict_foreign_free(
87 /*==============*/
88 	dict_foreign_t*	foreign);	/*!< in, own: foreign key struct */
89 /*********************************************************************//**
90 Finds the highest [number] for foreign key constraints of the table. Looks
91 only at the >= 4.0.18-format id's, which are of the form
92 databasename/tablename_ibfk_[number].
93 @return highest number, 0 if table has no new format foreign key constraints */
94 ulint
95 dict_table_get_highest_foreign_id(
96 /*==============================*/
97 	dict_table_t*	table);		/*!< in: table in the dictionary
98 					memory cache */
99 /********************************************************************//**
100 Return the end of table name where we have removed dbname and '/'.
101 @return table name */
102 const char*
103 dict_remove_db_name(
104 /*================*/
105 	const char*	name)	/*!< in: table name in the form
106 				dbname '/' tablename */
107 	MY_ATTRIBUTE((warn_unused_result));
108 
109 /** Operation to perform when opening a table */
110 enum dict_table_op_t {
111 	/** Expect the tablespace to exist. */
112 	DICT_TABLE_OP_NORMAL = 0,
113 	/** Drop any orphan indexes after an aborted online index creation */
114 	DICT_TABLE_OP_DROP_ORPHAN,
115 	/** Silently load the tablespace if it does not exist,
116 	and do not load the definitions of incomplete indexes. */
117 	DICT_TABLE_OP_LOAD_TABLESPACE
118 };
119 
120 /**********************************************************************//**
121 Returns a table object based on table id.
122 @return table, NULL if does not exist */
123 dict_table_t*
124 dict_table_open_on_id(
125 /*==================*/
126 	table_id_t	table_id,	/*!< in: table id */
127 	ibool		dict_locked,	/*!< in: TRUE=data dictionary locked */
128 	dict_table_op_t	table_op)	/*!< in: operation to perform */
129 	MY_ATTRIBUTE((warn_unused_result));
130 
131 dict_table_t*
132 dict_table_open_on_index_id(
133 /*==================*/
134         table_id_t      table_id,       /*!< in: table id */
135         bool            dict_locked)    /*!< in: TRUE=data dictionary locked */
136         __attribute__((warn_unused_result));
137 /********************************************************************//**
138 Decrements the count of open handles to a table. */
139 void
140 dict_table_close(
141 /*=============*/
142 	dict_table_t*	table,		/*!< in/out: table */
143 	ibool		dict_locked,	/*!< in: TRUE=data dictionary locked */
144 	ibool		try_drop);	/*!< in: TRUE=try to drop any orphan
145 					indexes after an aborted online
146 					index creation */
147 /*********************************************************************//**
148 Closes the only open handle to a table and drops a table while assuring
149 that dict_sys->mutex is held the whole time.  This assures that the table
150 is not evicted after the close when the count of open handles goes to zero.
151 Because dict_sys->mutex is held, we do not need to call
152 dict_table_prevent_eviction().  */
153 void
154 dict_table_close_and_drop(
155 /*======================*/
156 	trx_t*		trx,		/*!< in: data dictionary transaction */
157 	dict_table_t*	table);		/*!< in/out: table */
158 /**********************************************************************//**
159 Inits the data dictionary module. */
160 void
161 dict_init(void);
162 
163 /*********************************************************************//**
164 Gets the minimum number of bytes per character.
165 @return minimum multi-byte char size, in bytes */
166 UNIV_INLINE
167 ulint
168 dict_col_get_mbminlen(
169 /*==================*/
170 	const dict_col_t*	col)	/*!< in: column */
171 	MY_ATTRIBUTE((warn_unused_result));
172 /*********************************************************************//**
173 Gets the maximum number of bytes per character.
174 @return maximum multi-byte char size, in bytes */
175 UNIV_INLINE
176 ulint
177 dict_col_get_mbmaxlen(
178 /*==================*/
179 	const dict_col_t*	col)	/*!< in: column */
180 	MY_ATTRIBUTE((warn_unused_result));
181 /*********************************************************************//**
182 Sets the minimum and maximum number of bytes per character. */
183 UNIV_INLINE
184 void
185 dict_col_set_mbminmaxlen(
186 /*=====================*/
187 	dict_col_t*	col,		/*!< in/out: column */
188 	ulint		mbminlen,	/*!< in: minimum multi-byte
189 					character size, in bytes */
190 	ulint		mbmaxlen);	/*!< in: minimum multi-byte
191 					character size, in bytes */
192 
193 /*********************************************************************//**
194 Gets the column data type. */
195 UNIV_INLINE
196 void
197 dict_col_copy_type(
198 /*===============*/
199 	const dict_col_t*	col,	/*!< in: column */
200 	dtype_t*		type);	/*!< out: data type */
201 
202 /**********************************************************************//**
203 Determine bytes of column prefix to be stored in the undo log. Please
204 note if the table format is UNIV_FORMAT_A (< UNIV_FORMAT_B), no prefix
205 needs to be stored in the undo log.
206 @return bytes of column prefix to be stored in the undo log */
207 UNIV_INLINE
208 ulint
209 dict_max_field_len_store_undo(
210 /*==========================*/
211 	dict_table_t*		table,	/*!< in: table */
212 	const dict_col_t*	col)	/*!< in: column which index prefix
213 					is based on */
214 	MY_ATTRIBUTE((warn_unused_result));
215 
216 /** Determine maximum bytes of a virtual column need to be stored
217 in the undo log.
218 @param[in]	table		dict_table_t for the table
219 @param[in]	col_no		virtual column number
220 @return maximum bytes of virtual column to be stored in the undo log */
221 UNIV_INLINE
222 ulint
223 dict_max_v_field_len_store_undo(
224 	dict_table_t*		table,
225 	ulint			col_no);
226 
227 #endif /* !UNIV_HOTBACKUP */
228 #ifdef UNIV_DEBUG
229 /*********************************************************************//**
230 Assert that a column and a data type match.
231 @return TRUE */
232 UNIV_INLINE
233 ibool
234 dict_col_type_assert_equal(
235 /*=======================*/
236 	const dict_col_t*	col,	/*!< in: column */
237 	const dtype_t*		type)	/*!< in: data type */
238 	MY_ATTRIBUTE((warn_unused_result));
239 #endif /* UNIV_DEBUG */
240 #ifndef UNIV_HOTBACKUP
241 /***********************************************************************//**
242 Returns the minimum size of the column.
243 @return minimum size */
244 UNIV_INLINE
245 ulint
246 dict_col_get_min_size(
247 /*==================*/
248 	const dict_col_t*	col)	/*!< in: column */
249 	MY_ATTRIBUTE((warn_unused_result));
250 /***********************************************************************//**
251 Returns the maximum size of the column.
252 @return maximum size */
253 UNIV_INLINE
254 ulint
255 dict_col_get_max_size(
256 /*==================*/
257 	const dict_col_t*	col)	/*!< in: column */
258 	MY_ATTRIBUTE((warn_unused_result));
259 /***********************************************************************//**
260 Returns the size of a fixed size column, 0 if not a fixed size column.
261 @return fixed size, or 0 */
262 UNIV_INLINE
263 ulint
264 dict_col_get_fixed_size(
265 /*====================*/
266 	const dict_col_t*	col,	/*!< in: column */
267 	ulint			comp)	/*!< in: nonzero=ROW_FORMAT=COMPACT  */
268 	MY_ATTRIBUTE((warn_unused_result));
269 /***********************************************************************//**
270 Returns the ROW_FORMAT=REDUNDANT stored SQL NULL size of a column.
271 For fixed length types it is the fixed length of the type, otherwise 0.
272 @return SQL null storage size in ROW_FORMAT=REDUNDANT */
273 UNIV_INLINE
274 ulint
275 dict_col_get_sql_null_size(
276 /*=======================*/
277 	const dict_col_t*	col,	/*!< in: column */
278 	ulint			comp)	/*!< in: nonzero=ROW_FORMAT=COMPACT  */
279 	MY_ATTRIBUTE((warn_unused_result));
280 /*********************************************************************//**
281 Gets the column number.
282 @return col->ind, table column position (starting from 0) */
283 UNIV_INLINE
284 ulint
285 dict_col_get_no(
286 /*============*/
287 	const dict_col_t*	col)	/*!< in: column */
288 	MY_ATTRIBUTE((warn_unused_result));
289 /*********************************************************************//**
290 Gets the column position in the clustered index. */
291 UNIV_INLINE
292 ulint
293 dict_col_get_clust_pos(
294 /*===================*/
295 	const dict_col_t*	col,		/*!< in: table column */
296 	const dict_index_t*	clust_index)	/*!< in: clustered index */
297 	MY_ATTRIBUTE((warn_unused_result));
298 
299 /** Gets the column position in the given index.
300 @param[in]	col	table column
301 @param[in]	index	index to be searched for column
302 @return position of column in the given index. */
303 UNIV_INLINE
304 ulint
305 dict_col_get_index_pos(
306 	const dict_col_t*	col,
307 	const dict_index_t*	index)
308 	MY_ATTRIBUTE((warn_unused_result));
309 
310 /****************************************************************//**
311 If the given column name is reserved for InnoDB system columns, return
312 TRUE.
313 @return TRUE if name is reserved */
314 ibool
315 dict_col_name_is_reserved(
316 /*======================*/
317 	const char*	name)	/*!< in: column name */
318 	MY_ATTRIBUTE((warn_unused_result));
319 /********************************************************************//**
320 Acquire the autoinc lock. */
321 void
322 dict_table_autoinc_lock(
323 /*====================*/
324 	dict_table_t*	table);	/*!< in/out: table */
325 
326 /********************************************************************//**
327 Unconditionally set the autoinc counter. */
328 void
329 dict_table_autoinc_initialize(
330 /*==========================*/
331 	dict_table_t*	table,	/*!< in/out: table */
332 	ib_uint64_t	value);	/*!< in: next value to assign to a row */
333 
334 /** Store autoinc value when the table is evicted.
335 @param[in]	table	table evicted */
336 void
337 dict_table_autoinc_store(
338 	const dict_table_t*	table);
339 
340 /** Restore autoinc value when the table is loaded.
341 @param[in]	table	table loaded */
342 void
343 dict_table_autoinc_restore(
344 	dict_table_t*	table);
345 
346 /********************************************************************//**
347 Reads the next autoinc value (== autoinc counter value), 0 if not yet
348 initialized.
349 @return value for a new row, or 0 */
350 ib_uint64_t
351 dict_table_autoinc_read(
352 /*====================*/
353 	const dict_table_t*	table)	/*!< in: table */
354 	MY_ATTRIBUTE((warn_unused_result));
355 /********************************************************************//**
356 Updates the autoinc counter if the value supplied is greater than the
357 current value. */
358 void
359 dict_table_autoinc_update_if_greater(
360 /*=================================*/
361 
362 	dict_table_t*	table,	/*!< in/out: table */
363 	ib_uint64_t	value);	/*!< in: value which was assigned to a row */
364 /********************************************************************//**
365 Release the autoinc lock. */
366 void
367 dict_table_autoinc_unlock(
368 /*======================*/
369 	dict_table_t*	table);	/*!< in/out: table */
370 
371 /** Acquire the analyze index lock.
372 @param[in]	table table whose analyze_index latch to lock */
373 void
374 dict_table_analyze_index_lock(
375 	dict_table_t*	table);
376 
377 /** Release the analyze index lock.
378 @param[in]	table table whose analyze_index latch to unlock */
379 void
380 dict_table_analyze_index_unlock(
381 	dict_table_t*	table);
382 #endif /* !UNIV_HOTBACKUP */
383 /**********************************************************************//**
384 Adds system columns to a table object. */
385 void
386 dict_table_add_system_columns(
387 /*==========================*/
388 	dict_table_t*	table,	/*!< in/out: table */
389 	mem_heap_t*	heap);	/*!< in: temporary heap */
390 #ifndef UNIV_HOTBACKUP
391 /** Mark if table has big rows.
392 @param[in,out]	table	table handler */
393 void
394 dict_table_set_big_rows(
395 	dict_table_t*	table)
396 	MY_ATTRIBUTE((nonnull));
397 /**********************************************************************//**
398 Adds a table object to the dictionary cache. */
399 void
400 dict_table_add_to_cache(
401 /*====================*/
402 	dict_table_t*	table,		/*!< in: table */
403 	ibool		can_be_evicted,	/*!< in: TRUE if can be evicted*/
404 	mem_heap_t*	heap);		/*!< in: temporary heap */
405 
406 /**********************************************************************//**
407 Removes a table object from the dictionary cache. */
408 void
409 dict_table_remove_from_cache(
410 /*=========================*/
411 	dict_table_t*	table);	/*!< in, own: table */
412 
413 /**********************************************************************//**
414 Removes a table object from the dictionary cache. */
415 void
416 dict_table_remove_from_cache_low(
417 /*=============================*/
418 	dict_table_t*	table,		/*!< in, own: table */
419 	ibool		lru_evict);	/*!< in: TRUE if table being evicted
420 					to make room in the table LRU list */
421 /**********************************************************************//**
422 Renames a table object.
423 @return TRUE if success */
424 dberr_t
425 dict_table_rename_in_cache(
426 /*=======================*/
427 	dict_table_t*	table,		/*!< in/out: table */
428 	const char*	new_name,	/*!< in: new name */
429 	ibool		rename_also_foreigns)
430 					/*!< in: in ALTER TABLE we want
431 					to preserve the original table name
432 					in constraints which reference it */
433 	MY_ATTRIBUTE((warn_unused_result));
434 
435 /** Removes an index from the dictionary cache.
436 @param[in,out]	table	table whose index to remove
437 @param[in,out]	index	index to remove, this object is destroyed and must not
438 be accessed by the caller afterwards */
439 void
440 dict_index_remove_from_cache(
441 	dict_table_t*	table,
442 	dict_index_t*	index);
443 
444 /**********************************************************************//**
445 Change the id of a table object in the dictionary cache. This is used in
446 DISCARD TABLESPACE. */
447 void
448 dict_table_change_id_in_cache(
449 /*==========================*/
450 	dict_table_t*	table,	/*!< in/out: table object already in cache */
451 	table_id_t	new_id);	/*!< in: new id to set */
452 /**********************************************************************//**
453 Removes a foreign constraint struct from the dictionary cache. */
454 void
455 dict_foreign_remove_from_cache(
456 /*===========================*/
457 	dict_foreign_t*	foreign);	/*!< in, own: foreign constraint */
458 /**********************************************************************//**
459 Adds a foreign key constraint object to the dictionary cache. May free
460 the object if there already is an object with the same identifier in.
461 At least one of foreign table or referenced table must already be in
462 the dictionary cache!
463 @return DB_SUCCESS or error code */
464 dberr_t
465 dict_foreign_add_to_cache(
466 /*======================*/
467 	dict_foreign_t*		foreign,
468 				/*!< in, own: foreign key constraint */
469 	const char**		col_names,
470 				/*!< in: column names, or NULL to use
471 				foreign->foreign_table->col_names */
472 	bool			check_charsets,
473 				/*!< in: whether to check charset
474 				compatibility */
475 	dict_err_ignore_t	ignore_err)
476 				/*!< in: error to be ignored */
477 	MY_ATTRIBUTE((warn_unused_result));
478 /*********************************************************************//**
479 Checks if a table is referenced by foreign keys.
480 @return TRUE if table is referenced by a foreign key */
481 ibool
482 dict_table_is_referenced_by_foreign_key(
483 /*====================================*/
484 	const dict_table_t*	table)	/*!< in: InnoDB table */
485 	MY_ATTRIBUTE((warn_unused_result));
486 /**********************************************************************//**
487 Replace the index passed in with another equivalent index in the
488 foreign key lists of the table.
489 @return whether all replacements were found */
490 bool
491 dict_foreign_replace_index(
492 /*=======================*/
493 	dict_table_t*		table,  /*!< in/out: table */
494 	const char**		col_names,
495 					/*!< in: column names, or NULL
496 					to use table->col_names */
497 	const dict_index_t*	index)	/*!< in: index to be replaced */
498 	MY_ATTRIBUTE((warn_unused_result));
499 /**********************************************************************//**
500 Determines whether a string starts with the specified keyword.
501 @return TRUE if str starts with keyword */
502 ibool
503 dict_str_starts_with_keyword(
504 /*=========================*/
505 	THD*		thd,		/*!< in: MySQL thread handle */
506 	const char*	str,		/*!< in: string to scan for keyword */
507 	const char*	keyword)	/*!< in: keyword to look for */
508 	MY_ATTRIBUTE((warn_unused_result));
509 /** Scans a table create SQL string and adds to the data dictionary
510 the foreign key constraints declared in the string. This function
511 should be called after the indexes for a table have been created.
512 Each foreign key constraint must be accompanied with indexes in
513 bot participating tables. The indexes are allowed to contain more
514 fields than mentioned in the constraint.
515 
516 @param[in]	trx		transaction
517 @param[in]	sql_string	table create statement where
518 				foreign keys are declared like:
519 				FOREIGN KEY (a, b) REFERENCES table2(c, d),
520 				table2 can be written also with the database
521 				name before it: test.table2; the default
522 				database id the database of parameter name
523 @param[in]	sql_length	length of sql_string
524 @param[in]	name		table full name in normalized form
525 @param[in]	reject_fks	if TRUE, fail with error code
526 				DB_CANNOT_ADD_CONSTRAINT if any
527 				foreign keys are found.
528 @return error code or DB_SUCCESS */
529 dberr_t
530 dict_create_foreign_constraints(
531 	trx_t*			trx,
532 	const char*		sql_string,
533 	size_t			sql_length,
534 	const char*		name,
535 	ibool			reject_fks)
536 	MY_ATTRIBUTE((warn_unused_result));
537 /**********************************************************************//**
538 Parses the CONSTRAINT id's to be dropped in an ALTER TABLE statement.
539 @return DB_SUCCESS or DB_CANNOT_DROP_CONSTRAINT if syntax error or the
540 constraint id does not match */
541 dberr_t
542 dict_foreign_parse_drop_constraints(
543 /*================================*/
544 	mem_heap_t*	heap,			/*!< in: heap from which we can
545 						allocate memory */
546 	trx_t*		trx,			/*!< in: transaction */
547 	dict_table_t*	table,			/*!< in: table */
548 	ulint*		n,			/*!< out: number of constraints
549 						to drop */
550 	const char***	constraints_to_drop)	/*!< out: id's of the
551 						constraints to drop */
552 	MY_ATTRIBUTE((warn_unused_result));
553 /**********************************************************************//**
554 Returns a table object and increments its open handle count.
555 NOTE! This is a high-level function to be used mainly from outside the
556 'dict' directory. Inside this directory dict_table_get_low
557 is usually the appropriate function.
558 @param[in] table_name Table name
559 @param[in] dict_locked TRUE=data dictionary locked
560 @param[in] try_drop TRUE=try to drop any orphan indexes after
561 				an aborted online index creation
562 @param[in] ignore_err error to be ignored when loading the table
563 @return table, NULL if does not exist */
564 dict_table_t*
565 dict_table_open_on_name(
566 	const char*		table_name,
567 	ibool			dict_locked,
568 	ibool			try_drop,
569 	dict_err_ignore_t	ignore_err)
570 	MY_ATTRIBUTE((warn_unused_result));
571 
572 /*********************************************************************//**
573 Tries to find an index whose first fields are the columns in the array,
574 in the same order and is not marked for deletion and is not the same
575 as types_idx.
576 @return matching index, NULL if not found */
577 dict_index_t*
578 dict_foreign_find_index(
579 /*====================*/
580 	const dict_table_t*	table,	/*!< in: table */
581 	const char**		col_names,
582 					/*!< in: column names, or NULL
583 					to use table->col_names */
584 	const char**		columns,/*!< in: array of column names */
585 	ulint			n_cols,	/*!< in: number of columns */
586 	const dict_index_t*	types_idx,
587 					/*!< in: NULL or an index
588 					whose types the column types
589 					must match */
590 	bool			check_charsets,
591 					/*!< in: whether to check
592 					charsets.  only has an effect
593 					if types_idx != NULL */
594 	ulint			check_null)
595 					/*!< in: nonzero if none of
596 					the columns must be declared
597 					NOT NULL */
598 	MY_ATTRIBUTE((warn_unused_result));
599 /**********************************************************************//**
600 Returns a column's name.
601 @return column name. NOTE: not guaranteed to stay valid if table is
602 modified in any way (columns added, etc.). */
603 const char*
604 dict_table_get_col_name(
605 /*====================*/
606 	const dict_table_t*	table,	/*!< in: table */
607 	ulint			col_nr)	/*!< in: column number */
608 	MY_ATTRIBUTE((warn_unused_result));
609 
610 /** Returns a virtual column's name.
611 @param[in]	table		table object
612 @param[in]	col_nr		virtual column number(nth virtual column)
613 @return column name. */
614 const char*
615 dict_table_get_v_col_name(
616 	const dict_table_t*	table,
617 	ulint			col_nr);
618 
619 /** Check if the table has a given column.
620 @param[in]	table		table object
621 @param[in]	col_name	column name
622 @param[in]	col_nr		column number guessed, 0 as default
623 @return column number if the table has the specified column,
624 otherwise table->n_def */
625 ulint
626 dict_table_has_column(
627 	const dict_table_t*	table,
628 	const char*		col_name,
629 	ulint			col_nr = 0);
630 
631 /**********************************************************************//**
632 Outputs info on foreign keys of a table. */
633 void
634 dict_print_info_on_foreign_keys(
635 /*============================*/
636 	ibool		create_table_format, /*!< in: if TRUE then print in
637 				a format suitable to be inserted into
638 				a CREATE TABLE, otherwise in the format
639 				of SHOW TABLE STATUS */
640 	FILE*		file,	/*!< in: file where to print */
641 	trx_t*		trx,	/*!< in: transaction */
642 	dict_table_t*	table);	/*!< in: table */
643 /**********************************************************************//**
644 Outputs info on a foreign key of a table in a format suitable for
645 CREATE TABLE. */
646 void
647 dict_print_info_on_foreign_key_in_create_format(
648 /*============================================*/
649 	FILE*		file,		/*!< in: file where to print */
650 	trx_t*		trx,		/*!< in: transaction */
651 	dict_foreign_t*	foreign,	/*!< in: foreign key constraint */
652 	ibool		add_newline);	/*!< in: whether to add a newline */
653 /*********************************************************************//**
654 Tries to find an index whose first fields are the columns in the array,
655 in the same order and is not marked for deletion and is not the same
656 as types_idx.
657 @return matching index, NULL if not found */
658 bool
659 dict_foreign_qualify_index(
660 /*====================*/
661 	const dict_table_t*	table,	/*!< in: table */
662 	const char**		col_names,
663 					/*!< in: column names, or NULL
664 					to use table->col_names */
665 	const char**		columns,/*!< in: array of column names */
666 	ulint			n_cols,	/*!< in: number of columns */
667 	const dict_index_t*	index,	/*!< in: index to check */
668 	const dict_index_t*	types_idx,
669 					/*!< in: NULL or an index
670 					whose types the column types
671 					must match */
672 	bool			check_charsets,
673 					/*!< in: whether to check
674 					charsets.  only has an effect
675 					if types_idx != NULL */
676 	ulint			check_null)
677 					/*!< in: nonzero if none of
678 					the columns must be declared
679 					NOT NULL */
680 	MY_ATTRIBUTE((warn_unused_result));
681 #ifdef UNIV_DEBUG
682 /********************************************************************//**
683 Gets the first index on the table (the clustered index).
684 @return index, NULL if none exists */
685 UNIV_INLINE
686 dict_index_t*
687 dict_table_get_first_index(
688 /*=======================*/
689 	const dict_table_t*	table)	/*!< in: table */
690 	MY_ATTRIBUTE((warn_unused_result));
691 /********************************************************************//**
692 Gets the last index on the table.
693 @return index, NULL if none exists */
694 UNIV_INLINE
695 dict_index_t*
696 dict_table_get_last_index(
697 /*=======================*/
698 	const dict_table_t*	table)	/*!< in: table */
699 	MY_ATTRIBUTE((warn_unused_result));
700 /********************************************************************//**
701 Gets the next index on the table.
702 @return index, NULL if none left */
703 UNIV_INLINE
704 dict_index_t*
705 dict_table_get_next_index(
706 /*======================*/
707 	const dict_index_t*	index)	/*!< in: index */
708 	MY_ATTRIBUTE((warn_unused_result));
709 #else /* UNIV_DEBUG */
710 # define dict_table_get_first_index(table) UT_LIST_GET_FIRST((table)->indexes)
711 # define dict_table_get_last_index(table) UT_LIST_GET_LAST((table)->indexes)
712 # define dict_table_get_next_index(index) UT_LIST_GET_NEXT(indexes, index)
713 #endif /* UNIV_DEBUG */
714 #endif /* !UNIV_HOTBACKUP */
715 
716 /* Skip corrupted index */
717 #define dict_table_skip_corrupt_index(index)			\
718 	while (index && dict_index_is_corrupted(index)) {	\
719 		index = dict_table_get_next_index(index);	\
720 	}
721 
722 /* Get the next non-corrupt index */
723 #define dict_table_next_uncorrupted_index(index)		\
724 do {								\
725 	index = dict_table_get_next_index(index);		\
726 	dict_table_skip_corrupt_index(index);			\
727 } while (0)
728 
729 /********************************************************************//**
730 Check whether the index is the clustered index.
731 @return nonzero for clustered index, zero for other indexes */
732 UNIV_INLINE
733 ulint
734 dict_index_is_clust(
735 /*================*/
736 	const dict_index_t*	index)	/*!< in: index */
737 	MY_ATTRIBUTE((warn_unused_result));
738 
739 /** Check if index is auto-generated clustered index.
740 @param[in]	index	index
741 
742 @return true if index is auto-generated clustered index. */
743 UNIV_INLINE
744 bool
745 dict_index_is_auto_gen_clust(
746 	const dict_index_t*	index);
747 
748 /********************************************************************//**
749 Check whether the index is unique.
750 @return nonzero for unique index, zero for other indexes */
751 UNIV_INLINE
752 ulint
753 dict_index_is_unique(
754 /*=================*/
755 	const dict_index_t*	index)	/*!< in: index */
756 	MY_ATTRIBUTE((warn_unused_result));
757 /********************************************************************//**
758 Check whether the index is a Spatial Index.
759 @return	nonzero for Spatial Index, zero for other indexes */
760 UNIV_INLINE
761 ulint
762 dict_index_is_spatial(
763 /*==================*/
764 	const dict_index_t*	index)	/*!< in: index */
765 	MY_ATTRIBUTE((warn_unused_result));
766 /** Check whether the index contains a virtual column.
767 @param[in]	index	index
768 @return	nonzero for index on virtual column, zero for other indexes */
769 UNIV_INLINE
770 ulint
771 dict_index_has_virtual(
772 	const dict_index_t*	index);
773 /********************************************************************//**
774 Check whether the index is the insert buffer tree.
775 @return nonzero for insert buffer, zero for other indexes */
776 UNIV_INLINE
777 ulint
778 dict_index_is_ibuf(
779 /*===============*/
780 	const dict_index_t*	index)	/*!< in: index */
781 	MY_ATTRIBUTE((warn_unused_result));
782 /********************************************************************//**
783 Check whether the index is a secondary index or the insert buffer tree.
784 @return nonzero for insert buffer, zero for other indexes */
785 UNIV_INLINE
786 ulint
787 dict_index_is_sec_or_ibuf(
788 /*======================*/
789 	const dict_index_t*	index)	/*!< in: index */
790 	MY_ATTRIBUTE((warn_unused_result));
791 
792 /** Get all the FTS indexes on a table.
793 @param[in]	table	table
794 @param[out]	indexes	all FTS indexes on this table
795 @return number of FTS indexes */
796 ulint
797 dict_table_get_all_fts_indexes(
798 	const dict_table_t*	table,
799 	ib_vector_t*		indexes);
800 
801 /********************************************************************//**
802 Gets the number of user-defined non-virtual columns in a table in the
803 dictionary cache.
804 @return number of user-defined (e.g., not ROW_ID) non-virtual
805 columns of a table */
806 UNIV_INLINE
807 ulint
808 dict_table_get_n_user_cols(
809 /*=======================*/
810 	const dict_table_t*	table)	/*!< in: table */
811 	MY_ATTRIBUTE((warn_unused_result));
812 /** Gets the number of user-defined virtual and non-virtual columns in a table
813 in the dictionary cache.
814 @param[in]	table	table
815 @return number of user-defined (e.g., not ROW_ID) columns of a table */
816 UNIV_INLINE
817 ulint
818 dict_table_get_n_tot_u_cols(
819 	const dict_table_t*	table);
820 /********************************************************************//**
821 Gets the number of system columns in a table.
822 For intrinsic table on ROW_ID column is added for all other
823 tables TRX_ID and ROLL_PTR are all also appeneded.
824 @return number of system (e.g., ROW_ID) columns of a table */
825 UNIV_INLINE
826 ulint
827 dict_table_get_n_sys_cols(
828 /*======================*/
829 	const dict_table_t*	table)	/*!< in: table */
830 	MY_ATTRIBUTE((warn_unused_result));
831 /********************************************************************//**
832 Gets the number of all non-virtual columns (also system) in a table
833 in the dictionary cache.
834 @return number of columns of a table */
835 UNIV_INLINE
836 ulint
837 dict_table_get_n_cols(
838 /*==================*/
839 	const dict_table_t*	table)	/*!< in: table */
840 	MY_ATTRIBUTE((warn_unused_result));
841 
842 /** Gets the number of virtual columns in a table in the dictionary cache.
843 @param[in]	table	the table to check
844 @return number of virtual columns of a table */
845 UNIV_INLINE
846 ulint
847 dict_table_get_n_v_cols(
848 	const dict_table_t*	table);
849 
850 /** Check if a table has indexed virtual columns
851 @param[in]	table	the table to check
852 @return true is the table has indexed virtual columns */
853 UNIV_INLINE
854 bool
855 dict_table_has_indexed_v_cols(
856 	const dict_table_t*	table);
857 
858 /********************************************************************//**
859 Gets the approximately estimated number of rows in the table.
860 @return estimated number of rows */
861 UNIV_INLINE
862 ib_uint64_t
863 dict_table_get_n_rows(
864 /*==================*/
865 	const dict_table_t*	table)	/*!< in: table */
866 	MY_ATTRIBUTE((warn_unused_result));
867 /********************************************************************//**
868 Increment the number of rows in the table by one.
869 Notice that this operation is not protected by any latch, the number is
870 approximate. */
871 UNIV_INLINE
872 void
873 dict_table_n_rows_inc(
874 /*==================*/
875 	dict_table_t*	table);	/*!< in/out: table */
876 /********************************************************************//**
877 Decrement the number of rows in the table by one.
878 Notice that this operation is not protected by any latch, the number is
879 approximate. */
880 UNIV_INLINE
881 void
882 dict_table_n_rows_dec(
883 /*==================*/
884 	dict_table_t*	table);	/*!< in/out: table */
885 
886 /** Get nth virtual column
887 @param[in]	table	target table
888 @param[in]	col_nr	column number in MySQL Table definition
889 @return dict_v_col_t ptr */
890 dict_v_col_t*
891 dict_table_get_nth_v_col_mysql(
892 	const dict_table_t*	table,
893 	ulint			col_nr);
894 
895 #ifdef UNIV_DEBUG
896 /********************************************************************//**
897 Gets the nth column of a table.
898 @return pointer to column object */
899 UNIV_INLINE
900 dict_col_t*
901 dict_table_get_nth_col(
902 /*===================*/
903 	const dict_table_t*	table,	/*!< in: table */
904 	ulint			pos)	/*!< in: position of column */
905 	MY_ATTRIBUTE((warn_unused_result));
906 /** Gets the nth virtual column of a table.
907 @param[in]	table	table
908 @param[in]	pos	position of virtual column
909 @return pointer to virtual column object */
910 UNIV_INLINE
911 dict_v_col_t*
912 dict_table_get_nth_v_col(
913         const dict_table_t*	table,
914         ulint			pos);
915 /********************************************************************//**
916 Gets the given system column of a table.
917 @return pointer to column object */
918 UNIV_INLINE
919 dict_col_t*
920 dict_table_get_sys_col(
921 /*===================*/
922 	const dict_table_t*	table,	/*!< in: table */
923 	ulint			sys)	/*!< in: DATA_ROW_ID, ... */
924 	MY_ATTRIBUTE((warn_unused_result));
925 #else /* UNIV_DEBUG */
926 #define dict_table_get_nth_col(table, pos)	\
927 ((table)->cols + (pos))
928 #define dict_table_get_sys_col(table, sys)	\
929 ((table)->cols + (table)->n_cols + (sys)	\
930  - (dict_table_get_n_sys_cols(table)))
931 /* Get nth virtual columns */
932 #define dict_table_get_nth_v_col(table, pos)	((table)->v_cols + (pos))
933 #endif /* UNIV_DEBUG */
934 /********************************************************************//**
935 Gets the given system column number of a table.
936 @return column number */
937 UNIV_INLINE
938 ulint
939 dict_table_get_sys_col_no(
940 /*======================*/
941 	const dict_table_t*	table,	/*!< in: table */
942 	ulint			sys)	/*!< in: DATA_ROW_ID, ... */
943 	MY_ATTRIBUTE((warn_unused_result));
944 #ifndef UNIV_HOTBACKUP
945 /********************************************************************//**
946 Returns the minimum data size of an index record.
947 @return minimum data size in bytes */
948 UNIV_INLINE
949 ulint
950 dict_index_get_min_size(
951 /*====================*/
952 	const dict_index_t*	index)	/*!< in: index */
953 	MY_ATTRIBUTE((warn_unused_result));
954 #endif /* !UNIV_HOTBACKUP */
955 /********************************************************************//**
956 Check whether the table uses the compact page format.
957 @return TRUE if table uses the compact page format */
958 UNIV_INLINE
959 ibool
960 dict_table_is_comp(
961 /*===============*/
962 	const dict_table_t*	table)	/*!< in: table */
963 	MY_ATTRIBUTE((warn_unused_result));
964 
965 /********************************************************************//**
966 Determine the file format of a table.
967 @return file format version */
968 UNIV_INLINE
969 ulint
970 dict_table_get_format(
971 /*==================*/
972 	const dict_table_t*	table)	/*!< in: table */
973 	MY_ATTRIBUTE((warn_unused_result));
974 /********************************************************************//**
975 Determine the file format from a dict_table_t::flags.
976 @return file format version */
977 UNIV_INLINE
978 ulint
979 dict_tf_get_format(
980 /*===============*/
981 	ulint		flags)		/*!< in: dict_table_t::flags */
982 	MY_ATTRIBUTE((warn_unused_result));
983 
984 /** Set the various values in a dict_table_t::flags pointer.
985 @param[in,out]	flags,		Pointer to a 4 byte Table Flags
986 @param[in]	format,		File Format
987 @param[in]	zip_ssize	Zip Shift Size
988 @param[in]	use_data_dir	Table uses DATA DIRECTORY
989 @param[in]	shared_space	Table uses a General Shared Tablespace */
990 UNIV_INLINE
991 void
992 dict_tf_set(
993 	ulint*		flags,
994 	rec_format_t	format,
995 	ulint		zip_ssize,
996 	bool		use_data_dir,
997 	bool		shared_space);
998 
999 /** Initialize a dict_table_t::flags pointer.
1000 @param[in]	compact,	Table uses Compact or greater
1001 @param[in]	zip_ssize	Zip Shift Size (log 2 minus 9)
1002 @param[in]	atomic_blobs	Table uses Compressed or Dynamic
1003 @param[in]	data_dir	Table uses DATA DIRECTORY
1004 @param[in]	shared_space	Table uses a General Shared Tablespace */
1005 UNIV_INLINE
1006 ulint
1007 dict_tf_init(
1008 	bool		compact,
1009 	ulint		zip_ssize,
1010 	bool		atomic_blobs,
1011 	bool		data_dir,
1012 	bool		shared_space);
1013 
1014 /** Convert a 32 bit integer table flags to the 32 bit FSP Flags.
1015 Fsp Flags are written into the tablespace header at the offset
1016 FSP_SPACE_FLAGS and are also stored in the fil_space_t::flags field.
1017 The following chart shows the translation of the low order bit.
1018 Other bits are the same.
1019 ========================= Low order bit ==========================
1020                     | REDUNDANT | COMPACT | COMPRESSED | DYNAMIC
1021 dict_table_t::flags |     0     |    1    |     1      |    1
1022 fil_space_t::flags  |     0     |    0    |     1      |    1
1023 ==================================================================
1024 @param[in]	table_flags	dict_table_t::flags
1025 @param[in]	is_temp		whether the tablespace is temporary
1026 @param[in]	is_encrypted	whether the tablespace is encrypted
1027 @return tablespace flags (fil_space_t::flags) */
1028 ulint
1029 dict_tf_to_fsp_flags(
1030 	ulint	table_flags,
1031 	bool	is_temp,
1032 	bool	is_encrypted = false)
1033 	MY_ATTRIBUTE((const));
1034 
1035 /** Extract the page size from table flags.
1036 @param[in]	flags	flags
1037 @return compressed page size, or 0 if not compressed */
1038 UNIV_INLINE
1039 const page_size_t
1040 dict_tf_get_page_size(
1041 	ulint	flags)
1042 MY_ATTRIBUTE((const));
1043 
1044 /** Determine the extent size (in pages) for the given table
1045 @param[in]	table	the table whose extent size is being
1046 			calculated.
1047 @return extent size in pages (256, 128 or 64) */
1048 ulint
1049 dict_table_extent_size(
1050 	const dict_table_t*	table);
1051 
1052 /** Get the table page size.
1053 @param[in]	table	table
1054 @return compressed page size, or 0 if not compressed */
1055 UNIV_INLINE
1056 const page_size_t
1057 dict_table_page_size(
1058 	const dict_table_t*	table)
1059 	MY_ATTRIBUTE((warn_unused_result));
1060 
1061 #ifndef UNIV_HOTBACKUP
1062 /*********************************************************************//**
1063 Obtain exclusive locks on all index trees of the table. This is to prevent
1064 accessing index trees while InnoDB is updating internal metadata for
1065 operations such as truncate tables. */
1066 UNIV_INLINE
1067 void
1068 dict_table_x_lock_indexes(
1069 /*======================*/
1070 	dict_table_t*	table);	/*!< in: table */
1071 /*********************************************************************//**
1072 Release the exclusive locks on all index tree. */
1073 UNIV_INLINE
1074 void
1075 dict_table_x_unlock_indexes(
1076 /*========================*/
1077 	dict_table_t*	table);	/*!< in: table */
1078 /********************************************************************//**
1079 Checks if a column is in the ordering columns of the clustered index of a
1080 table. Column prefixes are treated like whole columns.
1081 @return TRUE if the column, or its prefix, is in the clustered key */
1082 ibool
1083 dict_table_col_in_clustered_key(
1084 /*============================*/
1085 	const dict_table_t*	table,	/*!< in: table */
1086 	ulint			n)	/*!< in: column number */
1087 	MY_ATTRIBUTE((warn_unused_result));
1088 /*******************************************************************//**
1089 Check if the table has an FTS index.
1090 @return TRUE if table has an FTS index */
1091 UNIV_INLINE
1092 ibool
1093 dict_table_has_fts_index(
1094 /*=====================*/
1095 	dict_table_t*   table)		/*!< in: table */
1096 	MY_ATTRIBUTE((warn_unused_result));
1097 /** Copies types of virtual columns contained in table to tuple and sets all
1098 fields of the tuple to the SQL NULL value.  This function should
1099 be called right after dtuple_create().
1100 @param[in,out]	tuple	data tuple
1101 @param[in]	table	table
1102 */
1103 void
1104 dict_table_copy_v_types(
1105 	dtuple_t*		tuple,
1106 	const dict_table_t*	table);
1107 
1108 /*******************************************************************//**
1109 Copies types of columns contained in table to tuple and sets all
1110 fields of the tuple to the SQL NULL value.  This function should
1111 be called right after dtuple_create(). */
1112 void
1113 dict_table_copy_types(
1114 /*==================*/
1115 	dtuple_t*		tuple,	/*!< in/out: data tuple */
1116 	const dict_table_t*	table);	/*!< in: table */
1117 /********************************************************************
1118 Wait until all the background threads of the given table have exited, i.e.,
1119 bg_threads == 0. Note: bg_threads_mutex must be reserved when
1120 calling this. */
1121 void
1122 dict_table_wait_for_bg_threads_to_exit(
1123 /*===================================*/
1124 	dict_table_t*	table,	/* in: table */
1125 	ulint		delay);	/* in: time in microseconds to wait between
1126 				checks of bg_threads. */
1127 /**********************************************************************//**
1128 Looks for an index with the given id. NOTE that we do not reserve
1129 the dictionary mutex: this function is for emergency purposes like
1130 printing info of a corrupt database page!
1131 @return index or NULL if not found from cache */
1132 dict_index_t*
1133 dict_index_find_on_id_low(
1134 /*======================*/
1135 	index_id_t	id)	/*!< in: index id */
1136 	MY_ATTRIBUTE((warn_unused_result));
1137 /**********************************************************************//**
1138 Make room in the table cache by evicting an unused table. The unused table
1139 should not be part of FK relationship and currently not used in any user
1140 transaction. There is no guarantee that it will remove a table.
1141 @return number of tables evicted. */
1142 ulint
1143 dict_make_room_in_cache(
1144 /*====================*/
1145 	ulint		max_tables,	/*!< in: max tables allowed in cache */
1146 	ulint		pct_check);	/*!< in: max percent to check */
1147 
1148 #define BIG_ROW_SIZE	1024
1149 
1150 /** Adds an index to the dictionary cache.
1151 @param[in]	table	table on which the index is
1152 @param[in]	index	index; NOTE! The index memory
1153 			object is freed in this function!
1154 @param[in]	page_no	root page number of the index
1155 @param[in]	strict	TRUE=refuse to create the index
1156 			if records could be too big to fit in
1157 			an B-tree page
1158 @return DB_SUCCESS, DB_TOO_BIG_RECORD, or DB_CORRUPTION */
1159 dberr_t
1160 dict_index_add_to_cache(
1161 	dict_table_t*	table,
1162 	dict_index_t*	index,
1163 	ulint		page_no,
1164 	ibool		strict)
1165 	MY_ATTRIBUTE((warn_unused_result));
1166 
1167 /** Clears the virtual column's index list before index is being freed.
1168 @param[in]  index   Index being freed */
1169 void
1170 dict_index_remove_from_v_col_list(
1171 	dict_index_t* index);
1172 
1173 /** Adds an index to the dictionary cache, with possible indexing newly
1174 added column.
1175 @param[in]	table	table on which the index is
1176 @param[in]	index	index; NOTE! The index memory
1177 			object is freed in this function!
1178 @param[in]	add_v	new virtual column that being added along with
1179 			an add index call
1180 @param[in]	page_no	root page number of the index
1181 @param[in]	strict	TRUE=refuse to create the index
1182 			if records could be too big to fit in
1183 			an B-tree page
1184 @return DB_SUCCESS, DB_TOO_BIG_RECORD, or DB_CORRUPTION */
1185 dberr_t
1186 dict_index_add_to_cache_w_vcol(
1187 	dict_table_t*		table,
1188 	dict_index_t*		index,
1189 	const dict_add_v_col_t* add_v,
1190 	ulint			page_no,
1191 	ibool			strict)
1192 	MY_ATTRIBUTE((warn_unused_result));
1193 #endif /* !UNIV_HOTBACKUP */
1194 /********************************************************************//**
1195 Gets the number of fields in the internal representation of an index,
1196 including fields added by the dictionary system.
1197 @return number of fields */
1198 UNIV_INLINE
1199 ulint
1200 dict_index_get_n_fields(
1201 /*====================*/
1202 	const dict_index_t*	index)	/*!< in: an internal
1203 					representation of index (in
1204 					the dictionary cache) */
1205 	MY_ATTRIBUTE((warn_unused_result));
1206 /********************************************************************//**
1207 Gets the number of fields in the internal representation of an index
1208 that uniquely determine the position of an index entry in the index, if
1209 we do not take multiversioning into account: in the B-tree use the value
1210 returned by dict_index_get_n_unique_in_tree.
1211 @return number of fields */
1212 UNIV_INLINE
1213 ulint
1214 dict_index_get_n_unique(
1215 /*====================*/
1216 	const dict_index_t*	index)	/*!< in: an internal representation
1217 					of index (in the dictionary cache) */
1218 	MY_ATTRIBUTE((warn_unused_result));
1219 /********************************************************************//**
1220 Gets the number of fields in the internal representation of an index
1221 which uniquely determine the position of an index entry in the index, if
1222 we also take multiversioning into account.
1223 @return number of fields */
1224 UNIV_INLINE
1225 ulint
1226 dict_index_get_n_unique_in_tree(
1227 /*============================*/
1228 	const dict_index_t*	index)	/*!< in: an internal representation
1229 					of index (in the dictionary cache) */
1230 	MY_ATTRIBUTE((warn_unused_result));
1231 
1232 /** The number of fields in the nonleaf page of spatial index, except
1233 the page no field. */
1234 #define DICT_INDEX_SPATIAL_NODEPTR_SIZE	1
1235 /**
1236 Gets the number of fields on nonleaf page level in the internal representation
1237 of an index which uniquely determine the position of an index entry in the
1238 index, if we also take multiversioning into account. Note, it doesn't
1239 include page no field.
1240 @param[in]	index	index
1241 @return number of fields */
1242 UNIV_INLINE
1243 ulint
1244 dict_index_get_n_unique_in_tree_nonleaf(
1245 	const dict_index_t*	index)
1246 	MY_ATTRIBUTE((warn_unused_result));
1247 /********************************************************************//**
1248 Gets the number of user-defined ordering fields in the index. In the internal
1249 representation we add the row id to the ordering fields to make all indexes
1250 unique, but this function returns the number of fields the user defined
1251 in the index as ordering fields.
1252 @return number of fields */
1253 UNIV_INLINE
1254 ulint
1255 dict_index_get_n_ordering_defined_by_user(
1256 /*======================================*/
1257 	const dict_index_t*	index)	/*!< in: an internal representation
1258 					of index (in the dictionary cache) */
1259 	MY_ATTRIBUTE((warn_unused_result));
1260 #ifdef UNIV_DEBUG
1261 /********************************************************************//**
1262 Gets the nth field of an index.
1263 @return pointer to field object */
1264 UNIV_INLINE
1265 dict_field_t*
1266 dict_index_get_nth_field(
1267 /*=====================*/
1268 	const dict_index_t*	index,	/*!< in: index */
1269 	ulint			pos)	/*!< in: position of field */
1270 	MY_ATTRIBUTE((warn_unused_result));
1271 #else /* UNIV_DEBUG */
1272 # define dict_index_get_nth_field(index, pos) ((index)->fields + (pos))
1273 #endif /* UNIV_DEBUG */
1274 /********************************************************************//**
1275 Gets pointer to the nth column in an index.
1276 @return column */
1277 UNIV_INLINE
1278 const dict_col_t*
1279 dict_index_get_nth_col(
1280 /*===================*/
1281 	const dict_index_t*	index,	/*!< in: index */
1282 	ulint			pos)	/*!< in: position of the field */
1283 	MY_ATTRIBUTE((warn_unused_result));
1284 /********************************************************************//**
1285 Gets the column number of the nth field in an index.
1286 @return column number */
1287 UNIV_INLINE
1288 ulint
1289 dict_index_get_nth_col_no(
1290 /*======================*/
1291 	const dict_index_t*	index,	/*!< in: index */
1292 	ulint			pos)	/*!< in: position of the field */
1293 	MY_ATTRIBUTE((warn_unused_result));
1294 /********************************************************************//**
1295 Looks for column n in an index.
1296 @return position in internal representation of the index;
1297 ULINT_UNDEFINED if not contained */
1298 UNIV_INLINE
1299 ulint
1300 dict_index_get_nth_col_pos(
1301 /*=======================*/
1302 	const dict_index_t*	index,	/*!< in: index */
1303 	ulint			n,	/*!< in: column number */
1304 	ulint*			prefix_col_pos) /*!< out: col num if prefix */
1305 	MY_ATTRIBUTE((nonnull(1), warn_unused_result));
1306 /** Looks for column n in an index.
1307 @param[in]	index		index
1308 @param[in]	n		column number
1309 @param[in]	inc_prefix	true=consider column prefixes too
1310 @param[in]	is_virtual	true==virtual column
1311 @param[in]	prefix_col_pos	col num if prefix
1312 @return position in internal representation of the index;
1313 ULINT_UNDEFINED if not contained */
1314 ulint
1315 dict_index_get_nth_col_or_prefix_pos(
1316 	const dict_index_t*	index,		/*!< in: index */
1317 	ulint			n,		/*!< in: column number */
1318 	bool			inc_prefix,	/*!< in: TRUE=consider
1319 						column prefixes too */
1320 	bool			is_virtual,	/*!< in: is a virtual column */
1321 	ulint*			prefix_col_pos)	/*!< out: col num if prefix */
1322 	MY_ATTRIBUTE((warn_unused_result));
1323 /********************************************************************//**
1324 Returns TRUE if the index contains a column or a prefix of that column.
1325 @param[in]	index		index
1326 @param[in]	n		column number
1327 @param[in]	is_virtual	whether it is a virtual col
1328 @return TRUE if contains the column or its prefix */
1329 ibool
1330 dict_index_contains_col_or_prefix(
1331 /*==============================*/
1332 	const dict_index_t*	index,	/*!< in: index */
1333 	ulint			n,	/*!< in: column number */
1334 	bool			is_virtual)
1335 					/*!< in: whether it is a virtual col */
1336 	MY_ATTRIBUTE((warn_unused_result));
1337 /********************************************************************//**
1338 Looks for a matching field in an index. The column has to be the same. The
1339 column in index must be complete, or must contain a prefix longer than the
1340 column in index2. That is, we must be able to construct the prefix in index2
1341 from the prefix in index.
1342 @return position in internal representation of the index;
1343 ULINT_UNDEFINED if not contained */
1344 ulint
1345 dict_index_get_nth_field_pos(
1346 /*=========================*/
1347 	const dict_index_t*	index,	/*!< in: index from which to search */
1348 	const dict_index_t*	index2,	/*!< in: index */
1349 	ulint			n)	/*!< in: field number in index2 */
1350 	MY_ATTRIBUTE((warn_unused_result));
1351 /********************************************************************//**
1352 Looks for column n position in the clustered index.
1353 @return position in internal representation of the clustered index */
1354 ulint
1355 dict_table_get_nth_col_pos(
1356 /*=======================*/
1357 	const dict_table_t*	table,	/*!< in: table */
1358 	ulint			n)	/*!< in: column number */
1359 	MY_ATTRIBUTE((warn_unused_result));
1360 /********************************************************************//**
1361 Returns the position of a system column in an index.
1362 @return position, ULINT_UNDEFINED if not contained */
1363 UNIV_INLINE
1364 ulint
1365 dict_index_get_sys_col_pos(
1366 /*=======================*/
1367 	const dict_index_t*	index,	/*!< in: index */
1368 	ulint			type)	/*!< in: DATA_ROW_ID, ... */
1369 	MY_ATTRIBUTE((warn_unused_result));
1370 /*******************************************************************//**
1371 Adds a column to index. */
1372 void
1373 dict_index_add_col(
1374 /*===============*/
1375 	dict_index_t*		index,		/*!< in/out: index */
1376 	const dict_table_t*	table,		/*!< in: table */
1377 	dict_col_t*		col,		/*!< in: column */
1378 	ulint			prefix_len);	/*!< in: column prefix length */
1379 #ifndef UNIV_HOTBACKUP
1380 /*******************************************************************//**
1381 Copies types of fields contained in index to tuple. */
1382 void
1383 dict_index_copy_types(
1384 /*==================*/
1385 	dtuple_t*		tuple,		/*!< in/out: data tuple */
1386 	const dict_index_t*	index,		/*!< in: index */
1387 	ulint			n_fields);	/*!< in: number of
1388 						field types to copy */
1389 #endif /* !UNIV_HOTBACKUP */
1390 /*********************************************************************//**
1391 Gets the field column.
1392 @return field->col, pointer to the table column */
1393 UNIV_INLINE
1394 const dict_col_t*
1395 dict_field_get_col(
1396 /*===============*/
1397 	const dict_field_t*	field)	/*!< in: index field */
1398 	MY_ATTRIBUTE((warn_unused_result));
1399 #ifndef UNIV_HOTBACKUP
1400 /**********************************************************************//**
1401 Returns an index object if it is found in the dictionary cache.
1402 Assumes that dict_sys->mutex is already being held.
1403 @return index, NULL if not found */
1404 dict_index_t*
1405 dict_index_get_if_in_cache_low(
1406 /*===========================*/
1407 	index_id_t	index_id)	/*!< in: index id */
1408 	MY_ATTRIBUTE((warn_unused_result));
1409 #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
1410 /**********************************************************************//**
1411 Returns an index object if it is found in the dictionary cache.
1412 @return index, NULL if not found */
1413 dict_index_t*
1414 dict_index_get_if_in_cache(
1415 /*=======================*/
1416 	index_id_t	index_id)	/*!< in: index id */
1417 	MY_ATTRIBUTE((warn_unused_result));
1418 #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
1419 #ifdef UNIV_DEBUG
1420 /**********************************************************************//**
1421 Checks that a tuple has n_fields_cmp value in a sensible range, so that
1422 no comparison can occur with the page number field in a node pointer.
1423 @return TRUE if ok */
1424 ibool
1425 dict_index_check_search_tuple(
1426 /*==========================*/
1427 	const dict_index_t*	index,	/*!< in: index tree */
1428 	const dtuple_t*		tuple)	/*!< in: tuple used in a search */
1429 	MY_ATTRIBUTE((warn_unused_result));
1430 /** Whether and when to allow temporary index names */
1431 enum check_name {
1432 	/** Require all indexes to be complete. */
1433 	CHECK_ALL_COMPLETE,
1434 	/** Allow aborted online index creation. */
1435 	CHECK_ABORTED_OK,
1436 	/** Allow partial indexes to exist. */
1437 	CHECK_PARTIAL_OK
1438 };
1439 /**********************************************************************//**
1440 Check for duplicate index entries in a table [using the index name] */
1441 void
1442 dict_table_check_for_dup_indexes(
1443 /*=============================*/
1444 	const dict_table_t*	table,	/*!< in: Check for dup indexes
1445 					in this table */
1446 	enum check_name		check);	/*!< in: whether and when to allow
1447 					temporary index names */
1448 #endif /* UNIV_DEBUG */
1449 /**********************************************************************//**
1450 Builds a node pointer out of a physical record and a page number.
1451 @return own: node pointer */
1452 dtuple_t*
1453 dict_index_build_node_ptr(
1454 /*======================*/
1455 	const dict_index_t*	index,	/*!< in: index */
1456 	const rec_t*		rec,	/*!< in: record for which to build node
1457 					pointer */
1458 	ulint			page_no,/*!< in: page number to put in node
1459 					pointer */
1460 	mem_heap_t*		heap,	/*!< in: memory heap where pointer
1461 					created */
1462 	ulint			level)	/*!< in: level of rec in tree:
1463 					0 means leaf level */
1464 	MY_ATTRIBUTE((warn_unused_result));
1465 /**********************************************************************//**
1466 Copies an initial segment of a physical record, long enough to specify an
1467 index entry uniquely.
1468 @return pointer to the prefix record */
1469 rec_t*
1470 dict_index_copy_rec_order_prefix(
1471 /*=============================*/
1472 	const dict_index_t*	index,	/*!< in: index */
1473 	const rec_t*		rec,	/*!< in: record for which to
1474 					copy prefix */
1475 	ulint*			n_fields,/*!< out: number of fields copied */
1476 	byte**			buf,	/*!< in/out: memory buffer for the
1477 					copied prefix, or NULL */
1478 	ulint*			buf_size)/*!< in/out: buffer size */
1479 	MY_ATTRIBUTE((warn_unused_result));
1480 /**********************************************************************//**
1481 Builds a typed data tuple out of a physical record.
1482 @return own: data tuple */
1483 dtuple_t*
1484 dict_index_build_data_tuple(
1485 /*========================*/
1486 	dict_index_t*	index,	/*!< in: index */
1487 	rec_t*		rec,	/*!< in: record for which to build data tuple */
1488 	ulint		n_fields,/*!< in: number of data fields */
1489 	mem_heap_t*	heap)	/*!< in: memory heap where tuple created */
1490 	MY_ATTRIBUTE((warn_unused_result));
1491 /*********************************************************************//**
1492 Gets the space id of the root of the index tree.
1493 @return space id */
1494 UNIV_INLINE
1495 ulint
1496 dict_index_get_space(
1497 /*=================*/
1498 	const dict_index_t*	index)	/*!< in: index */
1499 	MY_ATTRIBUTE((warn_unused_result));
1500 
1501 /*********************************************************************//**
1502 Sets the space id of the root of the index tree. */
1503 UNIV_INLINE
1504 void
1505 dict_index_set_space(
1506 /*=================*/
1507 	dict_index_t*	index,	/*!< in/out: index */
1508 	ulint		space);	/*!< in: space id */
1509 
1510 /*********************************************************************//**
1511 Gets the page number of the root of the index tree.
1512 @return page number */
1513 UNIV_INLINE
1514 ulint
1515 dict_index_get_page(
1516 /*================*/
1517 	const dict_index_t*	tree)	/*!< in: index */
1518 	MY_ATTRIBUTE((warn_unused_result));
1519 /*********************************************************************//**
1520 Gets the read-write lock of the index tree.
1521 @return read-write lock */
1522 UNIV_INLINE
1523 rw_lock_t*
1524 dict_index_get_lock(
1525 /*================*/
1526 	dict_index_t*	index)	/*!< in: index */
1527 	MY_ATTRIBUTE((warn_unused_result));
1528 /********************************************************************//**
1529 Returns free space reserved for future updates of records. This is
1530 relevant only in the case of many consecutive inserts, as updates
1531 which make the records bigger might fragment the index.
1532 @return number of free bytes on page, reserved for updates */
1533 UNIV_INLINE
1534 ulint
1535 dict_index_get_space_reserve(void);
1536 /*==============================*/
1537 
1538 /* Online index creation @{ */
1539 /********************************************************************//**
1540 Gets the status of online index creation.
1541 @return the status */
1542 UNIV_INLINE
1543 enum online_index_status
1544 dict_index_get_online_status(
1545 /*=========================*/
1546 	const dict_index_t*	index)	/*!< in: secondary index */
1547 	MY_ATTRIBUTE((warn_unused_result));
1548 
1549 /********************************************************************//**
1550 Sets the status of online index creation. */
1551 UNIV_INLINE
1552 void
1553 dict_index_set_online_status(
1554 /*=========================*/
1555 	dict_index_t*			index,		/*!< in/out: index */
1556 	enum online_index_status	status);	/*!< in: status */
1557 /********************************************************************//**
1558 Determines if a secondary index is being or has been created online,
1559 or if the table is being rebuilt online, allowing concurrent modifications
1560 to the table.
1561 @retval true if the index is being or has been built online, or
1562 if this is a clustered index and the table is being or has been rebuilt online
1563 @retval false if the index has been created or the table has been
1564 rebuilt completely */
1565 UNIV_INLINE
1566 bool
1567 dict_index_is_online_ddl(
1568 /*=====================*/
1569 	const dict_index_t*	index)	/*!< in: index */
1570 	MY_ATTRIBUTE((warn_unused_result));
1571 /*********************************************************************//**
1572 Calculates the minimum record length in an index. */
1573 ulint
1574 dict_index_calc_min_rec_len(
1575 /*========================*/
1576 	const dict_index_t*	index)	/*!< in: index */
1577 	MY_ATTRIBUTE((warn_unused_result));
1578 /********************************************************************//**
1579 Reserves the dictionary system mutex for MySQL. */
1580 void
1581 dict_mutex_enter_for_mysql(void);
1582 /*============================*/
1583 /********************************************************************//**
1584 Releases the dictionary system mutex for MySQL. */
1585 void
1586 dict_mutex_exit_for_mysql(void);
1587 /*===========================*/
1588 
1589 /** Create a dict_table_t's stats latch or delay for lazy creation.
1590 This function is only called from either single threaded environment
1591 or from a thread that has not shared the table object with other threads.
1592 @param[in,out]	table	table whose stats latch to create
1593 @param[in]	enabled	if false then the latch is disabled
1594 and dict_table_stats_lock()/unlock() become noop on this table. */
1595 void
1596 dict_table_stats_latch_create(
1597 	dict_table_t*	table,
1598 	bool		enabled);
1599 
1600 /** Destroy a dict_table_t's stats latch.
1601 This function is only called from either single threaded environment
1602 or from a thread that has not shared the table object with other threads.
1603 @param[in,out]	table	table whose stats latch to destroy */
1604 void
1605 dict_table_stats_latch_destroy(
1606 	dict_table_t*	table);
1607 
1608 /** Lock the appropriate latch to protect a given table's statistics.
1609 @param[in]	table		table whose stats to lock
1610 @param[in]	latch_mode	RW_S_LATCH or RW_X_LATCH */
1611 void
1612 dict_table_stats_lock(
1613 	dict_table_t*	table,
1614 	ulint		latch_mode);
1615 
1616 /** Unlock the latch that has been locked by dict_table_stats_lock().
1617 @param[in]	table		table whose stats to unlock
1618 @param[in]	latch_mode	RW_S_LATCH or RW_X_LATCH */
1619 void
1620 dict_table_stats_unlock(
1621 	dict_table_t*	table,
1622 	ulint		latch_mode);
1623 
1624 /********************************************************************//**
1625 Checks if the database name in two table names is the same.
1626 @return TRUE if same db name */
1627 ibool
1628 dict_tables_have_same_db(
1629 /*=====================*/
1630 	const char*	name1,	/*!< in: table name in the form
1631 				dbname '/' tablename */
1632 	const char*	name2)	/*!< in: table name in the form
1633 				dbname '/' tablename */
1634 	MY_ATTRIBUTE((warn_unused_result));
1635 /** Get an index by name.
1636 @param[in]	table		the table where to look for the index
1637 @param[in]	name		the index name to look for
1638 @param[in]	committed	true=search for committed,
1639 false=search for uncommitted
1640 @return index, NULL if does not exist */
1641 dict_index_t*
1642 dict_table_get_index_on_name(
1643 	dict_table_t*	table,
1644 	const char*	name,
1645 	bool		committed=true)
1646 	MY_ATTRIBUTE((warn_unused_result));
1647 /** Get an index by name.
1648 @param[in]	table		the table where to look for the index
1649 @param[in]	name		the index name to look for
1650 @param[in]	committed	true=search for committed,
1651 false=search for uncommitted
1652 @return index, NULL if does not exist */
1653 inline
1654 const dict_index_t*
1655 dict_table_get_index_on_name(
1656 	const dict_table_t*	table,
1657 	const char*		name,
1658 	bool			committed=true)
1659 {
1660 	return(dict_table_get_index_on_name(
1661 		       const_cast<dict_table_t*>(table), name, committed));
1662 }
1663 
1664 /***************************************************************
1665 Check whether a column exists in an FTS index. */
1666 UNIV_INLINE
1667 ulint
1668 dict_table_is_fts_column(
1669 /*=====================*/
1670 				/* out: ULINT_UNDEFINED if no match else
1671 				the offset within the vector */
1672 	ib_vector_t*	indexes,/* in: vector containing only FTS indexes */
1673 	ulint		col_no,	/* in: col number to search for */
1674 	bool		is_virtual)/*!< in: whether it is a virtual column */
1675 	MY_ATTRIBUTE((warn_unused_result));
1676 /**********************************************************************//**
1677 Prevent table eviction by moving a table to the non-LRU list from the
1678 LRU list if it is not already there. */
1679 UNIV_INLINE
1680 void
1681 dict_table_prevent_eviction(
1682 /*========================*/
1683 	dict_table_t*	table);	/*!< in: table to prevent eviction */
1684 /**********************************************************************//**
1685 Move a table to the non LRU end of the LRU list. */
1686 void
1687 dict_table_move_from_lru_to_non_lru(
1688 /*================================*/
1689 	dict_table_t*	table);	/*!< in: table to move from LRU to non-LRU */
1690 /** Looks for an index with the given id given a table instance.
1691 @param[in]	table	table instance
1692 @param[in]	id	index id
1693 @return index or NULL */
1694 dict_index_t*
1695 dict_table_find_index_on_id(
1696 	const dict_table_t*	table,
1697 	index_id_t		id);
1698 /**********************************************************************//**
1699 Move to the most recently used segment of the LRU list. */
1700 void
1701 dict_move_to_mru(
1702 /*=============*/
1703 	dict_table_t*	table);	/*!< in: table to move to MRU */
1704 
1705 /** Maximum number of columns in a foreign key constraint. Please Note MySQL
1706 has a much lower limit on the number of columns allowed in a foreign key
1707 constraint */
1708 #define MAX_NUM_FK_COLUMNS		500
1709 
1710 /* Buffers for storing detailed information about the latest foreign key
1711 and unique key errors */
1712 extern FILE*		dict_foreign_err_file;
1713 extern ib_mutex_t	dict_foreign_err_mutex; /* mutex protecting the
1714 						foreign key error messages */
1715 
1716 /** the dictionary system */
1717 extern dict_sys_t*	dict_sys;
1718 /** the data dictionary rw-latch protecting dict_sys */
1719 extern rw_lock_t*	dict_operation_lock;
1720 
1721 typedef std::map<table_id_t, ib_uint64_t> autoinc_map_t;
1722 
1723 /* Dictionary system struct */
1724 struct dict_sys_t{
1725 	DictSysMutex	mutex;		/*!< mutex protecting the data
1726 					dictionary; protects also the
1727 					disk-based dictionary system tables;
1728 					this mutex serializes CREATE TABLE
1729 					and DROP TABLE, as well as reading
1730 					the dictionary data for a table from
1731 					system tables */
1732 	row_id_t	row_id;		/*!< the next row id to assign;
1733 					NOTE that at a checkpoint this
1734 					must be written to the dict system
1735 					header and flushed to a file; in
1736 					recovery this must be derived from
1737 					the log records */
1738 	hash_table_t*	table_hash;	/*!< hash table of the tables, based
1739 					on name */
1740 	hash_table_t*	table_id_hash;	/*!< hash table of the tables, based
1741 					on id */
1742 	size_t		hash_size;	/*!< size of table_hash and
1743 					table_id_hash combined */
1744 	lint		size;		/*!< varying space in bytes occupied
1745 					by the data dictionary table and
1746 					index objects */
1747 	dict_table_t*	sys_tables;	/*!< SYS_TABLES table */
1748 	dict_table_t*	sys_columns;	/*!< SYS_COLUMNS table */
1749 	dict_table_t*	sys_indexes;	/*!< SYS_INDEXES table */
1750 	dict_table_t*	sys_fields;	/*!< SYS_FIELDS table */
1751 	dict_table_t*	sys_virtual;	/*!< SYS_VIRTUAL table */
1752 
1753 	/*=============================*/
1754 	UT_LIST_BASE_NODE_T(dict_table_t)
1755 			table_LRU;	/*!< List of tables that can be evicted
1756 					from the cache */
1757 	UT_LIST_BASE_NODE_T(dict_table_t)
1758 			table_non_LRU;	/*!< List of tables that can't be
1759 					evicted from the cache */
1760 	autoinc_map_t*	autoinc_map;	/*!< Map to store table id and autoinc
1761 					when table is evicted */
1762 
1763 	/** The first ID of the redo log pseudo-tablespace */
1764 	static const ulint		s_log_space_first_id = 0xFFFFFFF0UL;
1765  	/** Use maximum UINT value to indicate invalid space ID. */
1766 	static const ulint		s_invalid_space_id = 0xFFFFFFFF;
1767  	/** The data dictionary tablespace ID. The data dictionary
1768 	    tablespace does not exist in 5.7, but its ID added here
1769 	    for assertion checking. */
1770 	static const ulint		s_space_id = 0xFFFFFFFE;
1771  	/** The innodb_temporary tablespace ID. */
1772 	static const ulint		s_temp_space_id = 0xFFFFFFFD;
1773  	/** The lowest undo tablespace ID. */
1774 	static const ulint		s_min_undo_space_id
1775 		= s_log_space_first_id - TRX_SYS_N_RSEGS;
1776  	/** The highest undo  tablespace ID. */
1777 	static const ulint		s_max_undo_space_id
1778 		= s_log_space_first_id - 1;
1779  	/** The first reserved tablespace ID */
1780 	static const ulint		s_reserved_space_id =
1781 		s_min_undo_space_id;
1782 };
1783 #endif /* !UNIV_HOTBACKUP */
1784 
1785 /** dummy index for ROW_FORMAT=REDUNDANT supremum and infimum records */
1786 extern dict_index_t*	dict_ind_redundant;
1787 
1788 /**********************************************************************//**
1789 Inits dict_ind_redundant. */
1790 void
1791 dict_ind_init(void);
1792 /*===============*/
1793 
1794 /* Auxiliary structs for checking a table definition @{ */
1795 
1796 /* This struct is used to specify the name and type that a column must
1797 have when checking a table's schema. */
1798 struct dict_col_meta_t {
1799 	const char*	name;		/* column name */
1800 	ulint		mtype;		/* required column main type */
1801 	ulint		prtype_mask;	/* required column precise type mask;
1802 					if this is non-zero then all the
1803 					bits it has set must also be set
1804 					in the column's prtype */
1805 	ulint		len;		/* required column length */
1806 };
1807 
1808 /* This struct is used for checking whether a given table exists and
1809 whether it has a predefined schema (number of columns and column names
1810 and types) */
1811 struct dict_table_schema_t {
1812 	const char*		table_name;	/* the name of the table whose
1813 						structure we are checking */
1814 	ulint			n_cols;		/* the number of columns the
1815 						table must have */
1816 	dict_col_meta_t*	columns;	/* metadata for the columns;
1817 						this array has n_cols
1818 						elements */
1819 	ulint			n_foreign;	/* number of foreign keys this
1820 						table has, pointing to other
1821 						tables (where this table is
1822 						FK child) */
1823 	ulint			n_referenced;	/* number of foreign keys other
1824 						tables have, pointing to this
1825 						table (where this table is
1826 						parent) */
1827 };
1828 /* @} */
1829 
1830 /*********************************************************************//**
1831 Checks whether a table exists and whether it has the given structure.
1832 The table must have the same number of columns with the same names and
1833 types. The order of the columns does not matter.
1834 The caller must own the dictionary mutex.
1835 dict_table_schema_check() @{
1836 @return DB_SUCCESS if the table exists and contains the necessary columns */
1837 dberr_t
1838 dict_table_schema_check(
1839 /*====================*/
1840 	dict_table_schema_t*	req_schema,	/*!< in/out: required table
1841 						schema */
1842 	char*			errstr,		/*!< out: human readable error
1843 						message if != DB_SUCCESS and
1844 						!= DB_TABLE_NOT_FOUND is
1845 						returned */
1846 	size_t			errstr_sz)	/*!< in: errstr size */
1847 	MY_ATTRIBUTE((warn_unused_result));
1848 /* @} */
1849 
1850 /*********************************************************************//**
1851 Converts a database and table name from filesystem encoding
1852 (e.g. d@i1b/a@q1b@1Kc, same format as used in dict_table_t::name) in two
1853 strings in UTF8 encoding (e.g. dцb and aюbØc). The output buffers must be
1854 at least MAX_DB_UTF8_LEN and MAX_TABLE_UTF8_LEN bytes. */
1855 void
1856 dict_fs2utf8(
1857 /*=========*/
1858 	const char*	db_and_table,	/*!< in: database and table names,
1859 					e.g. d@i1b/a@q1b@1Kc */
1860 	char*		db_utf8,	/*!< out: database name, e.g. dцb */
1861 	size_t		db_utf8_size,	/*!< in: dbname_utf8 size */
1862 	char*		table_utf8,	/*!< out: table name, e.g. aюbØc */
1863 	size_t		table_utf8_size); /*!< in: table_utf8 size */
1864 
1865 /** Resize the hash tables besed on the current buffer pool size. */
1866 void
1867 dict_resize();
1868 
1869 /**********************************************************************//**
1870 Closes the data dictionary module. */
1871 void
1872 dict_close(void);
1873 /*============*/
1874 #ifndef UNIV_HOTBACKUP
1875 /**********************************************************************//**
1876 Check whether the table is corrupted.
1877 @return nonzero for corrupted table, zero for valid tables */
1878 UNIV_INLINE
1879 ulint
1880 dict_table_is_corrupted(
1881 /*====================*/
1882 	const dict_table_t*	table)	/*!< in: table */
1883 	MY_ATTRIBUTE((warn_unused_result));
1884 
1885 /**********************************************************************//**
1886 Check whether the index is corrupted.
1887 @return nonzero for corrupted index, zero for valid indexes */
1888 UNIV_INLINE
1889 ulint
1890 dict_index_is_corrupted(
1891 /*====================*/
1892 	const dict_index_t*	index)	/*!< in: index */
1893 	MY_ATTRIBUTE((warn_unused_result));
1894 
1895 #endif /* !UNIV_HOTBACKUP */
1896 /**********************************************************************//**
1897 Flags an index and table corrupted both in the data dictionary cache
1898 and in the system table SYS_INDEXES. */
1899 void
1900 dict_set_corrupted(
1901 /*===============*/
1902 	dict_index_t*	index,	/*!< in/out: index */
1903 	trx_t*		trx,	/*!< in/out: transaction */
1904 	const char*	ctx)	/*!< in: context */
1905 	UNIV_COLD;
1906 
1907 /** Flags an index corrupted in the data dictionary cache only. This
1908 is used mostly to mark a corrupted index when index's own dictionary
1909 is corrupted, and we force to load such index for repair purpose
1910 @param[in,out]	index	index that is corrupted */
1911 void
1912 dict_set_corrupted_index_cache_only(
1913 	dict_index_t*	index);
1914 
1915 /**********************************************************************//**
1916 Flags a table with specified space_id corrupted in the table dictionary
1917 cache.
1918 @return TRUE if successful */
1919 ibool
1920 dict_set_corrupted_by_space(
1921 /*========================*/
1922 	ulint		space_id);	/*!< in: space ID */
1923 
1924 bool dict_set_corrupted_by_space(const fil_space_t* space);
1925 
1926 /** Flag a table with specified space_id encrypted in the data dictionary
1927 cache
1928 @param[in]	space_id	Tablespace id */
1929 void
1930 dict_set_encrypted_by_space(
1931 	ulint	space_id);
1932 
1933 /** Sets merge_threshold in the SYS_INDEXES
1934 @param[in,out]	index		index
1935 @param[in]	merge_threshold	value to set */
1936 void
1937 dict_index_set_merge_threshold(
1938 	dict_index_t*	index,
1939 	ulint		merge_threshold);
1940 
1941 #ifdef UNIV_DEBUG
1942 /** Sets merge_threshold for all indexes in dictionary cache for debug.
1943 @param[in]	merge_threshold_all	value to set for all indexes */
1944 void
1945 dict_set_merge_threshold_all_debug(
1946 	uint	merge_threshold_all);
1947 #endif /* UNIV_DEBUG */
1948 
1949 /** Validate the table flags.
1950 @param[in]	flags	Table flags
1951 @return true if valid. */
1952 UNIV_INLINE
1953 bool
1954 dict_tf_is_valid(
1955 	ulint	flags);
1956 
1957 /** Validate both table flags and table flags2 and make sure they
1958 are compatible.
1959 @param[in]	flags	Table flags
1960 @param[in]	flags2	Table flags2
1961 @return true if valid. */
1962 UNIV_INLINE
1963 bool
1964 dict_tf2_is_valid(
1965 	ulint	flags,
1966 	ulint	flags2);
1967 
1968 /********************************************************************//**
1969 Check if the tablespace for the table has been discarded.
1970 @return true if the tablespace has been discarded. */
1971 UNIV_INLINE
1972 bool
1973 dict_table_is_discarded(
1974 /*====================*/
1975 	const dict_table_t*	table)	/*!< in: table to check */
1976 	MY_ATTRIBUTE((warn_unused_result));
1977 
1978 /********************************************************************//**
1979 Check if it is a temporary table.
1980 @return true if temporary table flag is set. */
1981 UNIV_INLINE
1982 bool
1983 dict_table_is_temporary(
1984 /*====================*/
1985 	const dict_table_t*	table)	/*!< in: table to check */
1986 	MY_ATTRIBUTE((warn_unused_result));
1987 
1988 /********************************************************************//**
1989 Check if it is a encrypted table.
1990 @return true if table encryption flag is set. */
1991 UNIV_INLINE
1992 bool
1993 dict_table_is_encrypted(
1994 /*====================*/
1995 	const dict_table_t*	table)	/*!< in: table to check */
1996 	MY_ATTRIBUTE((warn_unused_result));
1997 
1998 /** Check whether the table is intrinsic.
1999 An intrinsic table is a special kind of temporary table that
2000 is invisible to the end user.  It is created internally by the MySQL server
2001 layer or other module connected to InnoDB in order to gather and use data
2002 as part of a larger task.  Since access to it must be as fast as possible,
2003 it does not need UNDO semantics, system fields DB_TRX_ID & DB_ROLL_PTR,
2004 doublewrite, checksum, insert buffer, use of the shared data dictionary,
2005 locking, or even a transaction.  In short, these are not ACID tables at all,
2006 just temporary
2007 
2008 @param[in]	table	table to check
2009 @return true if intrinsic table flag is set. */
2010 UNIV_INLINE
2011 bool
2012 dict_table_is_intrinsic(
2013 	const dict_table_t*	table)
2014 	MY_ATTRIBUTE((warn_unused_result));
2015 
2016 /** Check if the table is in a shared tablespace (System or General).
2017 @param[in]	id	Space ID to check
2018 @return true if id is a shared tablespace, false if not. */
2019 UNIV_INLINE
2020 bool
2021 dict_table_in_shared_tablespace(
2022 	const dict_table_t*	table)
2023 	MY_ATTRIBUTE((warn_unused_result));
2024 
2025 /** Check whether locking is disabled for this table.
2026 Currently this is done for intrinsic table as their visibility is limited
2027 to the connection only.
2028 
2029 @param[in]	table	table to check
2030 @return true if locking is disabled. */
2031 UNIV_INLINE
2032 bool
2033 dict_table_is_locking_disabled(
2034 	const dict_table_t*	table)
2035 	MY_ATTRIBUTE((warn_unused_result));
2036 
2037 /********************************************************************//**
2038 Turn-off redo-logging if temporary table. */
2039 UNIV_INLINE
2040 void
2041 dict_disable_redo_if_temporary(
2042 /*===========================*/
2043 	const dict_table_t*	table,	/*!< in: table to check */
2044 	mtr_t*			mtr);	/*!< out: mini-transaction */
2045 
2046 /** Get table session row-id and increment the row-id counter for next use.
2047 @param[in,out]	table	table handler
2048 @return next table local row-id. */
2049 UNIV_INLINE
2050 row_id_t
2051 dict_table_get_next_table_sess_row_id(
2052 	dict_table_t*		table);
2053 
2054 /** Get table session trx-id and increment the trx-id counter for next use.
2055 @param[in,out]	table	table handler
2056 @return next table local trx-id. */
2057 UNIV_INLINE
2058 trx_id_t
2059 dict_table_get_next_table_sess_trx_id(
2060 	dict_table_t*		table);
2061 
2062 /** Get current session trx-id.
2063 @param[in]	table	table handler
2064 @return table local trx-id. */
2065 UNIV_INLINE
2066 trx_id_t
2067 dict_table_get_curr_table_sess_trx_id(
2068 	const dict_table_t*	table);
2069 
2070 #ifndef UNIV_HOTBACKUP
2071 /*********************************************************************//**
2072 This function should be called whenever a page is successfully
2073 compressed. Updates the compression padding information. */
2074 void
2075 dict_index_zip_success(
2076 /*===================*/
2077 	dict_index_t*	index);	/*!< in/out: index to be updated. */
2078 /*********************************************************************//**
2079 This function should be called whenever a page compression attempt
2080 fails. Updates the compression padding information. */
2081 void
2082 dict_index_zip_failure(
2083 /*===================*/
2084 	dict_index_t*	index);	/*!< in/out: index to be updated. */
2085 /*********************************************************************//**
2086 Return the optimal page size, for which page will likely compress.
2087 @return page size beyond which page may not compress*/
2088 ulint
2089 dict_index_zip_pad_optimal_page_size(
2090 /*=================================*/
2091 	dict_index_t*	index)	/*!< in: index for which page size
2092 				is requested */
2093 	MY_ATTRIBUTE((warn_unused_result));
2094 /*************************************************************//**
2095 Convert table flag to row format string.
2096 @return row format name */
2097 const char*
2098 dict_tf_to_row_format_string(
2099 /*=========================*/
2100 	ulint	table_flag);		/*!< in: row format setting */
2101 /****************************************************************//**
2102 Return maximum size of the node pointer record.
2103 @return maximum size of the record in bytes */
2104 ulint
2105 dict_index_node_ptr_max_size(
2106 /*=========================*/
2107 	const dict_index_t*	index)	/*!< in: index */
2108 	MY_ATTRIBUTE((warn_unused_result));
2109 /*****************************************************************//**
2110 Get index by first field of the index
2111 @return index which is having first field matches
2112 with the field present in field_index position of table */
2113 UNIV_INLINE
2114 dict_index_t*
2115 dict_table_get_index_on_first_col(
2116 /*==============================*/
2117 	const dict_table_t*	table,		/*!< in: table */
2118 	ulint			col_index);	/*!< in: position of column
2119 						in table */
2120 /** Check if a column is a virtual column
2121 @param[in]	col	column
2122 @return true if it is a virtual column, false otherwise */
2123 UNIV_INLINE
2124 bool
2125 dict_col_is_virtual(
2126 	const dict_col_t*	col);
2127 
2128 /** encode number of columns and number of virtual columns in one
2129 4 bytes value. We could do this because the number of columns in
2130 InnoDB is limited to 1017
2131 @param[in]	n_col	number of non-virtual column
2132 @param[in]	n_v_col	number of virtual column
2133 @return encoded value */
2134 UNIV_INLINE
2135 ulint
2136 dict_table_encode_n_col(
2137 	ulint	n_col,
2138 	ulint	n_v_col);
2139 
2140 /** Decode number of virtual and non-virtual columns in one 4 bytes value.
2141 @param[in]	encoded	encoded value
2142 @param[in,out]	n_col	number of non-virtual column
2143 @param[in,out]	n_v_col	number of virtual column */
2144 UNIV_INLINE
2145 void
2146 dict_table_decode_n_col(
2147 	ulint	encoded,
2148 	ulint*	n_col,
2149 	ulint*	n_v_col);
2150 
2151 /** Look for any dictionary objects that are found in the given tablespace.
2152 @param[in]	space_id	Tablespace ID to search for.
2153 @return true if tablespace is empty. */
2154 bool
2155 dict_space_is_empty(
2156 	ulint	space_id);
2157 
2158 /** Find the space_id for the given name in sys_tablespaces.
2159 @param[in]	name	Tablespace name to search for.
2160 @return the tablespace ID. */
2161 ulint
2162 dict_space_get_id(
2163 	const char*	name);
2164 
2165 /** Free the virtual column template
2166 @param[in,out]	vc_templ	virtual column template */
2167 UNIV_INLINE
2168 void
2169 dict_free_vc_templ(
2170 	dict_vcol_templ_t*	vc_templ);
2171 
2172 /** Check whether the table have virtual index.
2173 @param[in]	table	InnoDB table
2174 @return true if the table have virtual index, false otherwise. */
2175 UNIV_INLINE
2176 bool
2177 dict_table_have_virtual_index(
2178 	dict_table_t*	table);
2179 
2180 /** Allocate memory for intrinsic cache elements in the index
2181  * @param[in]      index   index object */
2182 UNIV_INLINE
2183 void
2184 dict_allocate_mem_intrinsic_cache(
2185                 dict_index_t*           index);
2186 
2187 /** Check whether the table is a partitioned table.
2188 @param[in]      table   Table to check.
2189 @return true if the table is a partitioned table else false. */
2190 UNIV_INLINE
2191 bool
2192 dict_table_is_partition(
2193         const dict_table_t*     table);
2194 
2195 /** @return true if all base column of virtual column is foreign key column
2196 @param[in]	vcol	in-memory virtul column
2197 @param[in]	foreign	in-memory Foreign key constraint */
2198 uint32_t dict_vcol_base_is_foreign_key(dict_v_col_t *vcol, dict_foreign_t *foreign);
2199 
2200 #endif /* !UNIV_HOTBACKUP */
2201 /*************************************************************************
2202 set is_corrupt flag by space_id*/
2203 
2204 void
2205 dict_table_set_corrupt_by_space(
2206 /*============================*/
2207 	ulint	space_id,
2208 	bool	need_mutex);
2209 
2210 /** Insert a records into SYS_ZIP_DICT.
2211 @retval	DB_SUCCESS	if OK
2212 @retval	dberr_t		if the insert failed */
2213 dberr_t
2214 dict_create_zip_dict(
2215 	const char*	name,		/*!< in: zip_dict name */
2216 	ulint		name_len,	/*!< in: zip_dict name length*/
2217 	const char*	data,		/*!< in: zip_dict data */
2218 	ulint		data_len);	/*!< in: zip_dict data length */
2219 
2220 /** Get single compression dictionary id for the given
2221 (table id, column pos) pair.
2222 @retval	DB_SUCCESS		if OK
2223 @retval	DB_RECORD_NOT_FOUND	if not found */
2224 dberr_t
2225 dict_get_dictionary_id_by_key(
2226 	table_id_t	table_id,	/*!< in: table id */
2227 	ulint		column_pos,	/*!< in: column position */
2228 	ulint*		dict_id,	/*!< out: zip_dict id */
2229 	bool		dict_locked);	/*!< in: true if data dictionary locked */
2230 
2231 
2232 /** Get compression dictionary info (name and data) for the given id.
2233 Allocates memory in name->str and data->str on success.
2234 Must be freed with mem_free().
2235 @retval	DB_SUCCESS		if OK
2236 @retval	DB_RECORD_NOT_FOUND	if not found */
2237 dberr_t
2238 dict_get_dictionary_info_by_id(
2239 	ulint	dict_id,	/*!< in: dictionary id */
2240 	char**	name,		/*!< out: dictionary name */
2241 	ulint*	name_len,	/*!< out: dictionary name length*/
2242 	char**	data,		/*!< out: dictionary data */
2243 	ulint*	data_len,	/*!< out: dictionary data length*/
2244 	bool	dict_locked);	/*!< in: true if data dictionary locked */
2245 
2246 /** Delete a record in SYS_ZIP_DICT with the given name.
2247 @retval	DB_SUCCESS		if OK
2248 @retval	DB_RECORD_NOT_FOUND	if not found
2249 @retval	DB_ROW_IS_REFERENCED	if in use */
2250 dberr_t
2251 dict_drop_zip_dict(
2252 	const char*	name,		/*!< in: zip_dict name */
2253 	ulint		name_len);	/*!< in: zip_dict name length*/
2254 
2255 #ifndef UNIV_NONINL
2256 #include "dict0dict.ic"
2257 #endif
2258 
2259 #endif
2260