1 /*****************************************************************************
2 
3 Copyright (c) 1996, 2018, 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/dict0dict.h
23 Data dictionary system
24 
25 Created 1/8/1996 Heikki Tuuri
26 *******************************************************/
27 
28 #ifndef dict0dict_h
29 #define dict0dict_h
30 
31 #include "data0data.h"
32 #include "dict0mem.h"
33 #include "fsp0fsp.h"
34 #include <deque>
35 
36 extern bool innodb_table_stats_not_found;
37 extern bool innodb_index_stats_not_found;
38 
39 /** the first table or index ID for other than hard-coded system tables */
40 constexpr uint8_t DICT_HDR_FIRST_ID= 10;
41 
42 /********************************************************************//**
43 Get the database name length in a table name.
44 @return database name length */
45 ulint
46 dict_get_db_name_len(
47 /*=================*/
48 	const char*	name)	/*!< in: table name in the form
49 				dbname '/' tablename */
50 	MY_ATTRIBUTE((nonnull, warn_unused_result));
51 /*********************************************************************//**
52 Open a table from its database and table name, this is currently used by
53 foreign constraint parser to get the referenced table.
54 @return complete table name with database and table name, allocated from
55 heap memory passed in */
56 char*
57 dict_get_referenced_table(
58 /*======================*/
59 	const char*	name,		/*!< in: foreign key table name */
60 	const char*	database_name,	/*!< in: table db name */
61 	ulint		database_name_len,/*!< in: db name length */
62 	const char*	table_name,	/*!< in: table name */
63 	ulint		table_name_len,	/*!< in: table name length */
64 	dict_table_t**	table,		/*!< out: table object or NULL */
65 	mem_heap_t*	heap);		/*!< in: heap memory */
66 /*********************************************************************//**
67 Frees a foreign key struct. */
68 void
69 dict_foreign_free(
70 /*==============*/
71 	dict_foreign_t*	foreign);	/*!< in, own: foreign key struct */
72 /*********************************************************************//**
73 Finds the highest [number] for foreign key constraints of the table. Looks
74 only at the >= 4.0.18-format id's, which are of the form
75 databasename/tablename_ibfk_[number].
76 @return highest number, 0 if table has no new format foreign key constraints */
77 ulint
78 dict_table_get_highest_foreign_id(
79 /*==============================*/
80 	dict_table_t*	table);		/*!< in: table in the dictionary
81 					memory cache */
82 /********************************************************************//**
83 Return the end of table name where we have removed dbname and '/'.
84 @return table name */
85 const char*
86 dict_remove_db_name(
87 /*================*/
88 	const char*	name)	/*!< in: table name in the form
89 				dbname '/' tablename */
90 	MY_ATTRIBUTE((nonnull, warn_unused_result));
91 
92 /** Operation to perform when opening a table */
93 enum dict_table_op_t {
94 	/** Expect the tablespace to exist. */
95 	DICT_TABLE_OP_NORMAL = 0,
96 	/** Drop any orphan indexes after an aborted online index creation */
97 	DICT_TABLE_OP_DROP_ORPHAN,
98 	/** Silently load the tablespace if it does not exist,
99 	and do not load the definitions of incomplete indexes. */
100 	DICT_TABLE_OP_LOAD_TABLESPACE,
101 	/** Open the table only if it's in table cache. */
102 	DICT_TABLE_OP_OPEN_ONLY_IF_CACHED
103 };
104 
105 /**********************************************************************//**
106 Returns a table object based on table id.
107 @return table, NULL if does not exist */
108 dict_table_t*
109 dict_table_open_on_id(
110 /*==================*/
111 	table_id_t	table_id,	/*!< in: table id */
112 	ibool		dict_locked,	/*!< in: TRUE=data dictionary locked */
113 	dict_table_op_t	table_op)	/*!< in: operation to perform */
114 	MY_ATTRIBUTE((warn_unused_result));
115 
116 /**********************************************************************//**
117 Returns a table object based on table id.
118 @return	table, NULL if does not exist */
119 dict_table_t* dict_table_open_on_index_id(index_id_t index_id)
120 	__attribute__((warn_unused_result));
121 /********************************************************************//**
122 Decrements the count of open handles to a table. */
123 void
124 dict_table_close(
125 /*=============*/
126 	dict_table_t*	table,		/*!< in/out: table */
127 	ibool		dict_locked,	/*!< in: TRUE=data dictionary locked */
128 	ibool		try_drop)	/*!< in: TRUE=try to drop any orphan
129 					indexes after an aborted online
130 					index creation */
131 	MY_ATTRIBUTE((nonnull));
132 /*********************************************************************//**
133 Closes the only open handle to a table and drops a table while assuring
134 that dict_sys.mutex is held the whole time.  This assures that the table
135 is not evicted after the close when the count of open handles goes to zero.
136 Because dict_sys.mutex is held, we do not need to call prevent_eviction(). */
137 void
138 dict_table_close_and_drop(
139 /*======================*/
140 	trx_t*		trx,		/*!< in: data dictionary transaction */
141 	dict_table_t*	table);		/*!< in/out: table */
142 
143 /*********************************************************************//**
144 Gets the minimum number of bytes per character.
145 @return minimum multi-byte char size, in bytes */
146 UNIV_INLINE
147 ulint
148 dict_col_get_mbminlen(
149 /*==================*/
150 	const dict_col_t*	col)	/*!< in: column */
151 	MY_ATTRIBUTE((nonnull, warn_unused_result));
152 /*********************************************************************//**
153 Gets the maximum number of bytes per character.
154 @return maximum multi-byte char size, in bytes */
155 UNIV_INLINE
156 ulint
157 dict_col_get_mbmaxlen(
158 /*==================*/
159 	const dict_col_t*	col)	/*!< in: column */
160 	MY_ATTRIBUTE((nonnull, warn_unused_result));
161 /*********************************************************************//**
162 Gets the column data type. */
163 UNIV_INLINE
164 void
165 dict_col_copy_type(
166 /*===============*/
167 	const dict_col_t*	col,	/*!< in: column */
168 	dtype_t*		type);	/*!< out: data type */
169 
170 /**********************************************************************//**
171 Determine bytes of column prefix to be stored in the undo log. Please
172 note that if !dict_table_has_atomic_blobs(table), no prefix
173 needs to be stored in the undo log.
174 @return bytes of column prefix to be stored in the undo log */
175 UNIV_INLINE
176 ulint
177 dict_max_field_len_store_undo(
178 /*==========================*/
179 	dict_table_t*		table,	/*!< in: table */
180 	const dict_col_t*	col)	/*!< in: column which index prefix
181 					is based on */
182 	MY_ATTRIBUTE((nonnull, warn_unused_result));
183 
184 /** Determine maximum bytes of a virtual column need to be stored
185 in the undo log.
186 @param[in]	table		dict_table_t for the table
187 @param[in]	col_no		virtual column number
188 @return maximum bytes of virtual column to be stored in the undo log */
189 UNIV_INLINE
190 ulint
191 dict_max_v_field_len_store_undo(
192 	dict_table_t*		table,
193 	ulint			col_no);
194 
195 #ifdef UNIV_DEBUG
196 /*********************************************************************//**
197 Assert that a column and a data type match.
198 @return TRUE */
199 UNIV_INLINE
200 ibool
201 dict_col_type_assert_equal(
202 /*=======================*/
203 	const dict_col_t*	col,	/*!< in: column */
204 	const dtype_t*		type)	/*!< in: data type */
205 	MY_ATTRIBUTE((nonnull, warn_unused_result));
206 #endif /* UNIV_DEBUG */
207 
208 /***********************************************************************//**
209 Returns the minimum size of the column.
210 @return minimum size */
211 UNIV_INLINE
212 ulint
213 dict_col_get_min_size(
214 /*==================*/
215 	const dict_col_t*	col)	/*!< in: column */
216 	MY_ATTRIBUTE((nonnull, warn_unused_result));
217 /***********************************************************************//**
218 Returns the maximum size of the column.
219 @return maximum size */
220 UNIV_INLINE
221 ulint
222 dict_col_get_max_size(
223 /*==================*/
224 	const dict_col_t*	col)	/*!< in: column */
225 	MY_ATTRIBUTE((nonnull, warn_unused_result));
226 /***********************************************************************//**
227 Returns the size of a fixed size column, 0 if not a fixed size column.
228 @return fixed size, or 0 */
229 UNIV_INLINE
230 ulint
231 dict_col_get_fixed_size(
232 /*====================*/
233 	const dict_col_t*	col,	/*!< in: column */
234 	ulint			comp)	/*!< in: nonzero=ROW_FORMAT=COMPACT  */
235 	MY_ATTRIBUTE((nonnull, warn_unused_result));
236 /***********************************************************************//**
237 Returns the ROW_FORMAT=REDUNDANT stored SQL NULL size of a column.
238 For fixed length types it is the fixed length of the type, otherwise 0.
239 @return SQL null storage size in ROW_FORMAT=REDUNDANT */
240 UNIV_INLINE
241 ulint
242 dict_col_get_sql_null_size(
243 /*=======================*/
244 	const dict_col_t*	col,	/*!< in: column */
245 	ulint			comp)	/*!< in: nonzero=ROW_FORMAT=COMPACT  */
246 	MY_ATTRIBUTE((nonnull, warn_unused_result));
247 /*********************************************************************//**
248 Gets the column number.
249 @return col->ind, table column position (starting from 0) */
250 UNIV_INLINE
251 ulint
252 dict_col_get_no(
253 /*============*/
254 	const dict_col_t*	col)	/*!< in: column */
255 	MY_ATTRIBUTE((nonnull, warn_unused_result));
256 /*********************************************************************//**
257 Gets the column position in the clustered index. */
258 UNIV_INLINE
259 ulint
260 dict_col_get_clust_pos(
261 /*===================*/
262 	const dict_col_t*	col,		/*!< in: table column */
263 	const dict_index_t*	clust_index)	/*!< in: clustered index */
264 	MY_ATTRIBUTE((nonnull, warn_unused_result));
265 
266 /** Gets the column position in the given index.
267 @param[in]	col	table column
268 @param[in]	index	index to be searched for column
269 @return position of column in the given index. */
270 UNIV_INLINE
271 ulint
272 dict_col_get_index_pos(
273 	const dict_col_t*	col,
274 	const dict_index_t*	index)
275 	MY_ATTRIBUTE((nonnull, warn_unused_result));
276 
277 /****************************************************************//**
278 If the given column name is reserved for InnoDB system columns, return
279 TRUE.
280 @return TRUE if name is reserved */
281 ibool
282 dict_col_name_is_reserved(
283 /*======================*/
284 	const char*	name)	/*!< in: column name */
285 	MY_ATTRIBUTE((nonnull, warn_unused_result));
286 /** Unconditionally set the AUTO_INCREMENT counter.
287 @param[in,out]	table	table or partition
288 @param[in]	value	next available AUTO_INCREMENT value */
289 MY_ATTRIBUTE((nonnull))
290 UNIV_INLINE
291 void
dict_table_autoinc_initialize(dict_table_t * table,ib_uint64_t value)292 dict_table_autoinc_initialize(dict_table_t* table, ib_uint64_t value)
293 {
294 	table->autoinc = value;
295 }
296 
297 /**
298 @param[in]	table	table or partition
299 @return the next AUTO_INCREMENT counter value
300 @retval	0	if AUTO_INCREMENT is not yet initialized */
301 MY_ATTRIBUTE((nonnull, warn_unused_result))
302 UNIV_INLINE
303 ib_uint64_t
dict_table_autoinc_read(const dict_table_t * table)304 dict_table_autoinc_read(const dict_table_t* table)
305 {
306 	return(table->autoinc);
307 }
308 
309 /** Update the AUTO_INCREMENT sequence if the value supplied is greater
310 than the current value.
311 @param[in,out]	table	table or partition
312 @param[in]	value	AUTO_INCREMENT value that was assigned to a row
313 @return	whether the AUTO_INCREMENT sequence was updated */
314 MY_ATTRIBUTE((nonnull))
315 UNIV_INLINE
316 bool
dict_table_autoinc_update_if_greater(dict_table_t * table,ib_uint64_t value)317 dict_table_autoinc_update_if_greater(dict_table_t* table, ib_uint64_t value)
318 {
319 	if (value > table->autoinc) {
320 
321 		table->autoinc = value;
322 		return(true);
323 	}
324 
325 	return(false);
326 }
327 
328 /**********************************************************************//**
329 Adds system columns to a table object. */
330 void
331 dict_table_add_system_columns(
332 /*==========================*/
333 	dict_table_t*	table,	/*!< in/out: table */
334 	mem_heap_t*	heap)	/*!< in: temporary heap */
335 	MY_ATTRIBUTE((nonnull));
336 /**********************************************************************//**
337 Renames a table object.
338 @return TRUE if success */
339 dberr_t
340 dict_table_rename_in_cache(
341 /*=======================*/
342 	dict_table_t*	table,		/*!< in/out: table */
343 	const char*	new_name,	/*!< in: new name */
344 	bool		rename_also_foreigns,
345 					/*!< in: in ALTER TABLE we want
346 					to preserve the original table name
347 					in constraints which reference it */
348 	bool		replace_new_file = false)
349 					/*!< in: whether to replace the
350 					file with the new name
351 					(as part of rolling back TRUNCATE) */
352 	MY_ATTRIBUTE((nonnull));
353 
354 /** Removes an index from the dictionary cache.
355 @param[in,out]	table	table whose index to remove
356 @param[in,out]	index	index to remove, this object is destroyed and must not
357 be accessed by the caller afterwards */
358 void
359 dict_index_remove_from_cache(
360 	dict_table_t*	table,
361 	dict_index_t*	index);
362 
363 /**********************************************************************//**
364 Change the id of a table object in the dictionary cache. This is used in
365 DISCARD TABLESPACE. */
366 void
367 dict_table_change_id_in_cache(
368 /*==========================*/
369 	dict_table_t*	table,	/*!< in/out: table object already in cache */
370 	table_id_t	new_id)	/*!< in: new id to set */
371 	MY_ATTRIBUTE((nonnull));
372 /**********************************************************************//**
373 Removes a foreign constraint struct from the dictionary cache. */
374 void
375 dict_foreign_remove_from_cache(
376 /*===========================*/
377 	dict_foreign_t*	foreign)	/*!< in, own: foreign constraint */
378 	MY_ATTRIBUTE((nonnull));
379 /**********************************************************************//**
380 Adds a foreign key constraint object to the dictionary cache. May free
381 the object if there already is an object with the same identifier in.
382 At least one of foreign table or referenced table must already be in
383 the dictionary cache!
384 @return DB_SUCCESS or error code */
385 dberr_t
386 dict_foreign_add_to_cache(
387 /*======================*/
388 	dict_foreign_t*		foreign,
389 				/*!< in, own: foreign key constraint */
390 	const char**		col_names,
391 				/*!< in: column names, or NULL to use
392 				foreign->foreign_table->col_names */
393 	bool			check_charsets,
394 				/*!< in: whether to check charset
395 				compatibility */
396 	dict_err_ignore_t	ignore_err)
397 				/*!< in: error to be ignored */
398 	MY_ATTRIBUTE((nonnull(1), warn_unused_result));
399 /*********************************************************************//**
400 Checks if a table is referenced by foreign keys.
401 @return TRUE if table is referenced by a foreign key */
402 ibool
403 dict_table_is_referenced_by_foreign_key(
404 /*====================================*/
405 	const dict_table_t*	table)	/*!< in: InnoDB table */
406 	MY_ATTRIBUTE((nonnull, warn_unused_result));
407 /**********************************************************************//**
408 Replace the index passed in with another equivalent index in the
409 foreign key lists of the table.
410 @return whether all replacements were found */
411 bool
412 dict_foreign_replace_index(
413 /*=======================*/
414 	dict_table_t*		table,  /*!< in/out: table */
415 	const char**		col_names,
416 					/*!< in: column names, or NULL
417 					to use table->col_names */
418 	const dict_index_t*	index)	/*!< in: index to be replaced */
419 	MY_ATTRIBUTE((nonnull(1,3), warn_unused_result));
420 /** Scans a table create SQL string and adds to the data dictionary
421 the foreign key constraints declared in the string. This function
422 should be called after the indexes for a table have been created.
423 Each foreign key constraint must be accompanied with indexes in
424 bot participating tables. The indexes are allowed to contain more
425 fields than mentioned in the constraint.
426 
427 @param[in]	trx		transaction
428 @param[in]	sql_string	table create statement where
429 				foreign keys are declared like:
430 				FOREIGN KEY (a, b) REFERENCES table2(c, d),
431 				table2 can be written also with the database
432 				name before it: test.table2; the default
433 				database id the database of parameter name
434 @param[in]	sql_length	length of sql_string
435 @param[in]	name		table full name in normalized form
436 @param[in]	reject_fks	if TRUE, fail with error code
437 				DB_CANNOT_ADD_CONSTRAINT if any
438 				foreign keys are found.
439 @return error code or DB_SUCCESS */
440 dberr_t
441 dict_create_foreign_constraints(
442 	trx_t*			trx,
443 	const char*		sql_string,
444 	size_t			sql_length,
445 	const char*		name,
446 	ibool			reject_fks)
447 	MY_ATTRIBUTE((warn_unused_result));
448 /**********************************************************************//**
449 Parses the CONSTRAINT id's to be dropped in an ALTER TABLE statement.
450 @return DB_SUCCESS or DB_CANNOT_DROP_CONSTRAINT if syntax error or the
451 constraint id does not match */
452 dberr_t
453 dict_foreign_parse_drop_constraints(
454 /*================================*/
455 	mem_heap_t*	heap,			/*!< in: heap from which we can
456 						allocate memory */
457 	trx_t*		trx,			/*!< in: transaction */
458 	dict_table_t*	table,			/*!< in: table */
459 	ulint*		n,			/*!< out: number of constraints
460 						to drop */
461 	const char***	constraints_to_drop)	/*!< out: id's of the
462 						constraints to drop */
463 	MY_ATTRIBUTE((nonnull, warn_unused_result));
464 /**********************************************************************//**
465 Returns a table object and increments its open handle count.
466 NOTE! This is a high-level function to be used mainly from outside the
467 'dict' directory. Inside this directory dict_table_get_low
468 is usually the appropriate function.
469 @param[in] table_name Table name
470 @param[in] dict_locked TRUE=data dictionary locked
471 @param[in] try_drop TRUE=try to drop any orphan indexes after
472 				an aborted online index creation
473 @param[in] ignore_err error to be ignored when loading the table
474 @return table, NULL if does not exist */
475 dict_table_t*
476 dict_table_open_on_name(
477 	const char*		table_name,
478 	ibool			dict_locked,
479 	ibool			try_drop,
480 	dict_err_ignore_t	ignore_err)
481 	MY_ATTRIBUTE((warn_unused_result));
482 
483 /** Outcome of dict_foreign_find_index() or dict_foreign_qualify_index() */
484 enum fkerr_t
485 {
486   /** A backing index was found for a FOREIGN KEY constraint */
487   FK_SUCCESS = 0,
488   /** There is no index that covers the columns in the constraint. */
489   FK_INDEX_NOT_FOUND,
490   /** The index is for a prefix index, not a full column. */
491   FK_IS_PREFIX_INDEX,
492   /** A condition of SET NULL conflicts with a NOT NULL column. */
493   FK_COL_NOT_NULL,
494   /** The column types do not match */
495   FK_COLS_NOT_EQUAL
496 };
497 
498 /*********************************************************************//**
499 Tries to find an index whose first fields are the columns in the array,
500 in the same order and is not marked for deletion and is not the same
501 as types_idx.
502 @return matching index, NULL if not found */
503 dict_index_t*
504 dict_foreign_find_index(
505 /*====================*/
506 	const dict_table_t*	table,	/*!< in: table */
507 	const char**		col_names,
508 					/*!< in: column names, or NULL
509 					to use table->col_names */
510 	const char**		columns,/*!< in: array of column names */
511 	ulint			n_cols,	/*!< in: number of columns */
512 	const dict_index_t*	types_idx,
513 					/*!< in: NULL or an index
514 					whose types the column types
515 					must match */
516 	bool			check_charsets,
517 					/*!< in: whether to check
518 					charsets.  only has an effect
519 					if types_idx != NULL */
520 	ulint			check_null,
521 					/*!< in: nonzero if none of
522 					the columns must be declared
523 					NOT NULL */
524 	fkerr_t*		error = NULL,	/*!< out: error code */
525 	ulint*			err_col_no = NULL,
526 					/*!< out: column number where
527 					error happened */
528 	dict_index_t**		err_index = NULL)
529 					/*!< out: index where error
530 					happened */
531 
532 	MY_ATTRIBUTE((nonnull(1,3), warn_unused_result));
533 
534 /** Returns a virtual column's name.
535 @param[in]	table		table object
536 @param[in]	col_nr		virtual column number(nth virtual column)
537 @return column name. */
538 const char*
539 dict_table_get_v_col_name(
540 	const dict_table_t*	table,
541 	ulint			col_nr);
542 
543 /** Check if the table has a given column.
544 @param[in]	table		table object
545 @param[in]	col_name	column name
546 @param[in]	col_nr		column number guessed, 0 as default
547 @return column number if the table has the specified column,
548 otherwise table->n_def */
549 ulint
550 dict_table_has_column(
551 	const dict_table_t*	table,
552 	const char*		col_name,
553 	ulint			col_nr = 0);
554 
555 /**********************************************************************//**
556 Outputs info on foreign keys of a table. */
557 std::string
558 dict_print_info_on_foreign_keys(
559 /*============================*/
560 	ibool		create_table_format, /*!< in: if TRUE then print in
561 				a format suitable to be inserted into
562 				a CREATE TABLE, otherwise in the format
563 				of SHOW TABLE STATUS */
564 	trx_t*		trx,	/*!< in: transaction */
565 	dict_table_t*	table);	/*!< in: table */
566 
567 /**********************************************************************//**
568 Outputs info on a foreign key of a table in a format suitable for
569 CREATE TABLE. */
570 std::string
571 dict_print_info_on_foreign_key_in_create_format(
572 /*============================================*/
573 	trx_t*		trx,		/*!< in: transaction */
574 	dict_foreign_t*	foreign,	/*!< in: foreign key constraint */
575 	ibool		add_newline);	/*!< in: whether to add a newline */
576 
577 /*********************************************************************//**
578 Tries to find an index whose first fields are the columns in the array,
579 in the same order and is not marked for deletion and is not the same
580 as types_idx.
581 @return matching index, NULL if not found */
582 bool
583 dict_foreign_qualify_index(
584 /*====================*/
585 	const dict_table_t*	table,	/*!< in: table */
586 	const char**		col_names,
587 					/*!< in: column names, or NULL
588 					to use table->col_names */
589 	const char**		columns,/*!< in: array of column names */
590 	ulint			n_cols,	/*!< in: number of columns */
591 	const dict_index_t*	index,	/*!< in: index to check */
592 	const dict_index_t*	types_idx,
593 					/*!< in: NULL or an index
594 					whose types the column types
595 					must match */
596 	bool			check_charsets,
597 					/*!< in: whether to check
598 					charsets.  only has an effect
599 					if types_idx != NULL */
600 	ulint			check_null,
601 					/*!< in: nonzero if none of
602 					the columns must be declared
603 					NOT NULL */
604 	fkerr_t*		error,	/*!< out: error code */
605 	ulint*			err_col_no,
606 					/*!< out: column number where
607 					error happened */
608 	dict_index_t**		err_index)
609 					/*!< out: index where error
610 					happened */
611 	MY_ATTRIBUTE((nonnull(1,3), warn_unused_result));
612 #ifdef UNIV_DEBUG
613 /********************************************************************//**
614 Gets the first index on the table (the clustered index).
615 @return index, NULL if none exists */
616 UNIV_INLINE
617 dict_index_t*
618 dict_table_get_first_index(
619 /*=======================*/
620 	const dict_table_t*	table)	/*!< in: table */
621 	MY_ATTRIBUTE((nonnull, warn_unused_result));
622 /********************************************************************//**
623 Gets the last index on the table.
624 @return index, NULL if none exists */
625 UNIV_INLINE
626 dict_index_t*
627 dict_table_get_last_index(
628 /*=======================*/
629 	const dict_table_t*	table)	/*!< in: table */
630 	MY_ATTRIBUTE((nonnull, warn_unused_result));
631 /********************************************************************//**
632 Gets the next index on the table.
633 @return index, NULL if none left */
634 UNIV_INLINE
635 dict_index_t*
636 dict_table_get_next_index(
637 /*======================*/
638 	const dict_index_t*	index)	/*!< in: index */
639 	MY_ATTRIBUTE((nonnull, warn_unused_result));
640 #else /* UNIV_DEBUG */
641 # define dict_table_get_first_index(table) UT_LIST_GET_FIRST((table)->indexes)
642 # define dict_table_get_last_index(table) UT_LIST_GET_LAST((table)->indexes)
643 # define dict_table_get_next_index(index) UT_LIST_GET_NEXT(indexes, index)
644 #endif /* UNIV_DEBUG */
645 
646 /* Skip corrupted index */
647 #define dict_table_skip_corrupt_index(index)			\
648 	while (index && index->is_corrupted()) {		\
649 		index = dict_table_get_next_index(index);	\
650 	}
651 
652 /* Get the next non-corrupt index */
653 #define dict_table_next_uncorrupted_index(index)		\
654 do {								\
655 	index = dict_table_get_next_index(index);		\
656 	dict_table_skip_corrupt_index(index);			\
657 } while (0)
658 
659 #define dict_index_is_clust(index) (index)->is_clust()
660 #define dict_index_is_auto_gen_clust(index) (index)->is_gen_clust()
661 #define dict_index_is_unique(index) (index)->is_unique()
662 #define dict_index_is_spatial(index) (index)->is_spatial()
663 #define dict_index_is_ibuf(index) (index)->is_ibuf()
664 #define dict_index_is_sec_or_ibuf(index) !(index)->is_primary()
665 #define dict_index_has_virtual(index) (index)->has_virtual()
666 
667 /** Get all the FTS indexes on a table.
668 @param[in]	table	table
669 @param[out]	indexes	all FTS indexes on this table
670 @return number of FTS indexes */
671 ulint
672 dict_table_get_all_fts_indexes(
673 	const dict_table_t*	table,
674 	ib_vector_t*		indexes);
675 
676 /********************************************************************//**
677 Gets the number of user-defined non-virtual columns in a table in the
678 dictionary cache.
679 @return number of user-defined (e.g., not ROW_ID) non-virtual
680 columns of a table */
681 UNIV_INLINE
682 ulint
683 dict_table_get_n_user_cols(
684 /*=======================*/
685 	const dict_table_t*	table)	/*!< in: table */
686 	MY_ATTRIBUTE((warn_unused_result));
687 /********************************************************************//**
688 Gets the number of all non-virtual columns (also system) in a table
689 in the dictionary cache.
690 @return number of columns of a table */
691 UNIV_INLINE
692 ulint
693 dict_table_get_n_cols(
694 /*==================*/
695 	const dict_table_t*	table)	/*!< in: table */
696 	MY_ATTRIBUTE((warn_unused_result));
697 
698 /** Gets the number of virtual columns in a table in the dictionary cache.
699 @param[in]	table	the table to check
700 @return number of virtual columns of a table */
701 UNIV_INLINE
702 ulint
703 dict_table_get_n_v_cols(
704 	const dict_table_t*	table);
705 
706 /** Check if a table has indexed virtual columns
707 @param[in]	table	the table to check
708 @return true is the table has indexed virtual columns */
709 UNIV_INLINE
710 bool
711 dict_table_has_indexed_v_cols(
712 	const dict_table_t*	table);
713 
714 /********************************************************************//**
715 Gets the approximately estimated number of rows in the table.
716 @return estimated number of rows */
717 UNIV_INLINE
718 ib_uint64_t
719 dict_table_get_n_rows(
720 /*==================*/
721 	const dict_table_t*	table)	/*!< in: table */
722 	MY_ATTRIBUTE((warn_unused_result));
723 /********************************************************************//**
724 Increment the number of rows in the table by one.
725 Notice that this operation is not protected by any latch, the number is
726 approximate. */
727 UNIV_INLINE
728 void
729 dict_table_n_rows_inc(
730 /*==================*/
731 	dict_table_t*	table)	/*!< in/out: table */
732 	MY_ATTRIBUTE((nonnull));
733 /********************************************************************//**
734 Decrement the number of rows in the table by one.
735 Notice that this operation is not protected by any latch, the number is
736 approximate. */
737 UNIV_INLINE
738 void
739 dict_table_n_rows_dec(
740 /*==================*/
741 	dict_table_t*	table)	/*!< in/out: table */
742 	MY_ATTRIBUTE((nonnull));
743 
744 /** Get nth virtual column
745 @param[in]	table	target table
746 @param[in]	col_nr	column number in MySQL Table definition
747 @return dict_v_col_t ptr */
748 dict_v_col_t*
749 dict_table_get_nth_v_col_mysql(
750 	const dict_table_t*	table,
751 	ulint			col_nr);
752 
753 #ifdef UNIV_DEBUG
754 /********************************************************************//**
755 Gets the nth column of a table.
756 @return pointer to column object */
757 UNIV_INLINE
758 dict_col_t*
759 dict_table_get_nth_col(
760 /*===================*/
761 	const dict_table_t*	table,	/*!< in: table */
762 	ulint			pos)	/*!< in: position of column */
763 	MY_ATTRIBUTE((nonnull, warn_unused_result));
764 /** Gets the nth virtual column of a table.
765 @param[in]	table	table
766 @param[in]	pos	position of virtual column
767 @return pointer to virtual column object */
768 UNIV_INLINE
769 dict_v_col_t*
770 dict_table_get_nth_v_col(
771         const dict_table_t*	table,
772         ulint			pos);
773 /********************************************************************//**
774 Gets the given system column of a table.
775 @return pointer to column object */
776 UNIV_INLINE
777 dict_col_t*
778 dict_table_get_sys_col(
779 /*===================*/
780 	const dict_table_t*	table,	/*!< in: table */
781 	ulint			sys)	/*!< in: DATA_ROW_ID, ... */
782 	MY_ATTRIBUTE((nonnull, warn_unused_result));
783 #else /* UNIV_DEBUG */
784 #define dict_table_get_nth_col(table, pos)	(&(table)->cols[pos])
785 #define dict_table_get_sys_col(table, sys)	\
786 	&(table)->cols[(table)->n_cols + (sys) - DATA_N_SYS_COLS]
787 /* Get nth virtual columns */
788 #define dict_table_get_nth_v_col(table, pos)	(&(table)->v_cols[pos])
789 #endif /* UNIV_DEBUG */
790 /** Wrapper function.
791 @see dict_col_t::name()
792 @param[in]	table	table
793 @param[in]	col_nr	column number in table
794 @return	column name */
795 inline
796 const char*
dict_table_get_col_name(const dict_table_t * table,ulint col_nr)797 dict_table_get_col_name(const dict_table_t* table, ulint col_nr)
798 {
799 	return(dict_table_get_nth_col(table, col_nr)->name(*table));
800 }
801 
802 /********************************************************************//**
803 Gets the given system column number of a table.
804 @return column number */
805 UNIV_INLINE
806 ulint
807 dict_table_get_sys_col_no(
808 /*======================*/
809 	const dict_table_t*	table,	/*!< in: table */
810 	ulint			sys)	/*!< in: DATA_ROW_ID, ... */
811 	MY_ATTRIBUTE((nonnull, warn_unused_result));
812 
813 /********************************************************************//**
814 Returns the minimum data size of an index record.
815 @return minimum data size in bytes */
816 UNIV_INLINE
817 ulint
818 dict_index_get_min_size(
819 /*====================*/
820 	const dict_index_t*	index)	/*!< in: index */
821 	MY_ATTRIBUTE((nonnull, warn_unused_result));
822 
823 #define dict_table_is_comp(table) (table)->not_redundant()
824 
825 /** Determine if a table uses atomic BLOBs (no locally stored prefix).
826 @param[in]	table	InnoDB table
827 @return whether BLOBs are atomic */
828 inline
829 bool
dict_table_has_atomic_blobs(const dict_table_t * table)830 dict_table_has_atomic_blobs(const dict_table_t* table)
831 {
832 	return(DICT_TF_HAS_ATOMIC_BLOBS(table->flags));
833 }
834 
835 /** @return potential max length stored inline for externally stored fields */
get_overflow_field_local_len()836 inline size_t dict_table_t::get_overflow_field_local_len() const
837 {
838 	if (dict_table_has_atomic_blobs(this)) {
839 		/* ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED: do not
840 		store any BLOB prefix locally */
841 		return BTR_EXTERN_FIELD_REF_SIZE;
842 	}
843 	/* up to MySQL 5.1: store a 768-byte prefix locally */
844 	return BTR_EXTERN_FIELD_REF_SIZE + DICT_ANTELOPE_MAX_INDEX_COL_LEN;
845 }
846 
847 /** Set the various values in a dict_table_t::flags pointer.
848 @param[in,out]	flags,		Pointer to a 4 byte Table Flags
849 @param[in]	format,		File Format
850 @param[in]	zip_ssize	Zip Shift Size
851 @param[in]	use_data_dir	Table uses DATA DIRECTORY
852 @param[in]	page_compressed Table uses page compression
853 @param[in]	page_compression_level Page compression level */
854 UNIV_INLINE
855 void
856 dict_tf_set(
857 	ulint*		flags,
858 	rec_format_t	format,
859 	ulint		zip_ssize,
860 	bool		use_data_dir,
861 	bool		page_compressed,
862 	ulint		page_compression_level);
863 
864 /** Convert a 32 bit integer table flags to the 32 bit FSP Flags.
865 Fsp Flags are written into the tablespace header at the offset
866 FSP_SPACE_FLAGS and are also stored in the fil_space_t::flags field.
867 The following chart shows the translation of the low order bit.
868 Other bits are the same.
869 ========================= Low order bit ==========================
870                     | REDUNDANT | COMPACT | COMPRESSED | DYNAMIC
871 dict_table_t::flags |     0     |    1    |     1      |    1
872 fil_space_t::flags  |     0     |    0    |     1      |    1
873 ==================================================================
874 @param[in]	table_flags	dict_table_t::flags
875 @return tablespace flags (fil_space_t::flags) */
876 UNIV_INLINE
877 ulint
878 dict_tf_to_fsp_flags(ulint table_flags)
879 	MY_ATTRIBUTE((const));
880 
881 
882 /** Extract the ROW_FORMAT=COMPRESSED page size from table flags.
883 @param[in]	flags	flags
884 @return ROW_FORMAT=COMPRESSED page size
885 @retval	0 if not compressed */
dict_tf_get_zip_size(ulint flags)886 inline ulint dict_tf_get_zip_size(ulint flags)
887 {
888 	flags &= DICT_TF_MASK_ZIP_SSIZE;
889 	return flags
890 		? (UNIV_ZIP_SIZE_MIN >> 1)
891 		<< (FSP_FLAGS_GET_ZIP_SSIZE(flags >> DICT_TF_POS_ZIP_SSIZE
892 					    << FSP_FLAGS_POS_ZIP_SSIZE))
893 		: 0;
894 }
895 
896 /********************************************************************//**
897 Checks if a column is in the ordering columns of the clustered index of a
898 table. Column prefixes are treated like whole columns.
899 @return TRUE if the column, or its prefix, is in the clustered key */
900 ibool
901 dict_table_col_in_clustered_key(
902 /*============================*/
903 	const dict_table_t*	table,	/*!< in: table */
904 	ulint			n)	/*!< in: column number */
905 	MY_ATTRIBUTE((nonnull, warn_unused_result));
906 /*******************************************************************//**
907 Check if the table has an FTS index.
908 @return TRUE if table has an FTS index */
909 UNIV_INLINE
910 ibool
911 dict_table_has_fts_index(
912 /*=====================*/
913 	dict_table_t*   table)		/*!< in: table */
914 	MY_ATTRIBUTE((nonnull, warn_unused_result));
915 /** Copies types of virtual columns contained in table to tuple and sets all
916 fields of the tuple to the SQL NULL value.  This function should
917 be called right after dtuple_create().
918 @param[in,out]	tuple	data tuple
919 @param[in]	table	table
920 */
921 void
922 dict_table_copy_v_types(
923 	dtuple_t*		tuple,
924 	const dict_table_t*	table);
925 
926 /*******************************************************************//**
927 Copies types of columns contained in table to tuple and sets all
928 fields of the tuple to the SQL NULL value.  This function should
929 be called right after dtuple_create(). */
930 void
931 dict_table_copy_types(
932 /*==================*/
933 	dtuple_t*		tuple,	/*!< in/out: data tuple */
934 	const dict_table_t*	table)	/*!< in: table */
935 	MY_ATTRIBUTE((nonnull));
936 /**********************************************************************//**
937 Looks for an index with the given id. NOTE that we do not reserve
938 the dictionary mutex: this function is for emergency purposes like
939 printing info of a corrupt database page!
940 @return index or NULL if not found from cache */
941 dict_index_t*
942 dict_index_find_on_id_low(
943 /*======================*/
944 	index_id_t	id)	/*!< in: index id */
945 	MY_ATTRIBUTE((warn_unused_result));
946 /**********************************************************************//**
947 Make room in the table cache by evicting an unused table. The unused table
948 should not be part of FK relationship and currently not used in any user
949 transaction. There is no guarantee that it will remove a table.
950 @return number of tables evicted. */
951 ulint
952 dict_make_room_in_cache(
953 /*====================*/
954 	ulint		max_tables,	/*!< in: max tables allowed in cache */
955 	ulint		pct_check);	/*!< in: max percent to check */
956 
957 /** Adds an index to the dictionary cache, with possible indexing newly
958 added column.
959 @param[in,out]	index	index; NOTE! The index memory
960 			object is freed in this function!
961 @param[in]	page_no	root page number of the index
962 @param[in]	add_v	virtual columns being added along with ADD INDEX
963 @return DB_SUCCESS, or DB_CORRUPTION */
964 dberr_t
965 dict_index_add_to_cache(
966 	dict_index_t*&		index,
967 	ulint			page_no,
968 	const dict_add_v_col_t* add_v = NULL)
969 	MY_ATTRIBUTE((warn_unused_result));
970 /********************************************************************//**
971 Gets the number of fields in the internal representation of an index,
972 including fields added by the dictionary system.
973 @return number of fields */
974 UNIV_INLINE
975 ulint
976 dict_index_get_n_fields(
977 /*====================*/
978 	const dict_index_t*	index)	/*!< in: an internal
979 					representation of index (in
980 					the dictionary cache) */
981 	MY_ATTRIBUTE((nonnull, warn_unused_result));
982 
983 /********************************************************************//**
984 Gets the number of fields in the internal representation of an index
985 that uniquely determine the position of an index entry in the index, if
986 we do not take multiversioning into account: in the B-tree use the value
987 returned by dict_index_get_n_unique_in_tree.
988 @return number of fields */
989 UNIV_INLINE
990 ulint
991 dict_index_get_n_unique(
992 /*====================*/
993 	const dict_index_t*	index)	/*!< in: an internal representation
994 					of index (in the dictionary cache) */
995 	MY_ATTRIBUTE((nonnull, warn_unused_result));
996 /********************************************************************//**
997 Gets the number of fields in the internal representation of an index
998 which uniquely determine the position of an index entry in the index, if
999 we also take multiversioning into account.
1000 @return number of fields */
1001 UNIV_INLINE
1002 ulint
1003 dict_index_get_n_unique_in_tree(
1004 /*============================*/
1005 	const dict_index_t*	index)	/*!< in: an internal representation
1006 					of index (in the dictionary cache) */
1007 	MY_ATTRIBUTE((nonnull, warn_unused_result));
1008 
1009 /** The number of fields in the nonleaf page of spatial index, except
1010 the page no field. */
1011 #define DICT_INDEX_SPATIAL_NODEPTR_SIZE	1
1012 /**
1013 Gets the number of fields on nonleaf page level in the internal representation
1014 of an index which uniquely determine the position of an index entry in the
1015 index, if we also take multiversioning into account. Note, it doesn't
1016 include page no field.
1017 @param[in]	index	index
1018 @return number of fields */
1019 UNIV_INLINE
1020 ulint
1021 dict_index_get_n_unique_in_tree_nonleaf(
1022 	const dict_index_t*	index)
1023 	MY_ATTRIBUTE((nonnull, warn_unused_result));
1024 /********************************************************************//**
1025 Gets the number of user-defined ordering fields in the index. In the internal
1026 representation we add the row id to the ordering fields to make all indexes
1027 unique, but this function returns the number of fields the user defined
1028 in the index as ordering fields.
1029 @return number of fields */
1030 UNIV_INLINE
1031 ulint
1032 dict_index_get_n_ordering_defined_by_user(
1033 /*======================================*/
1034 	const dict_index_t*	index)	/*!< in: an internal representation
1035 					of index (in the dictionary cache) */
1036 	MY_ATTRIBUTE((nonnull, warn_unused_result));
1037 #ifdef UNIV_DEBUG
1038 /********************************************************************//**
1039 Gets the nth field of an index.
1040 @return pointer to field object */
1041 UNIV_INLINE
1042 dict_field_t*
1043 dict_index_get_nth_field(
1044 /*=====================*/
1045 	const dict_index_t*	index,	/*!< in: index */
1046 	ulint			pos)	/*!< in: position of field */
1047 	MY_ATTRIBUTE((nonnull, warn_unused_result));
1048 #else /* UNIV_DEBUG */
1049 # define dict_index_get_nth_field(index, pos) ((index)->fields + (pos))
1050 #endif /* UNIV_DEBUG */
1051 /********************************************************************//**
1052 Gets pointer to the nth column in an index.
1053 @return column */
1054 UNIV_INLINE
1055 const dict_col_t*
1056 dict_index_get_nth_col(
1057 /*===================*/
1058 	const dict_index_t*	index,	/*!< in: index */
1059 	ulint			pos)	/*!< in: position of the field */
1060 	MY_ATTRIBUTE((nonnull, warn_unused_result));
1061 /********************************************************************//**
1062 Gets the column number of the nth field in an index.
1063 @return column number */
1064 UNIV_INLINE
1065 ulint
1066 dict_index_get_nth_col_no(
1067 /*======================*/
1068 	const dict_index_t*	index,	/*!< in: index */
1069 	ulint			pos)	/*!< in: position of the field */
1070 	MY_ATTRIBUTE((nonnull, warn_unused_result));
1071 /********************************************************************//**
1072 Looks for column n in an index.
1073 @return position in internal representation of the index;
1074 ULINT_UNDEFINED if not contained */
1075 UNIV_INLINE
1076 ulint
1077 dict_index_get_nth_col_pos(
1078 /*=======================*/
1079 	const dict_index_t*	index,	/*!< in: index */
1080 	ulint			n,	/*!< in: column number */
1081 	ulint*			prefix_col_pos) /*!< out: col num if prefix */
1082 	MY_ATTRIBUTE((nonnull(1), warn_unused_result));
1083 
1084 /** Looks for column n in an index.
1085 @param[in]	index		index
1086 @param[in]	n		column number
1087 @param[in]	inc_prefix	true=consider column prefixes too
1088 @param[in]	is_virtual	true==virtual column
1089 @return position in internal representation of the index;
1090 ULINT_UNDEFINED if not contained */
1091 ulint
1092 dict_index_get_nth_col_or_prefix_pos(
1093 	const dict_index_t*	index,		/*!< in: index */
1094 	ulint			n,		/*!< in: column number */
1095 	bool			inc_prefix,	/*!< in: TRUE=consider
1096 						column prefixes too */
1097 	bool			is_virtual,	/*!< in: is a virtual column
1098 						*/
1099 	ulint*			prefix_col_pos) /*!< out: col num if prefix
1100 						*/
1101 	__attribute__((warn_unused_result));
1102 /********************************************************************//**
1103 Looks for a matching field in an index. The column has to be the same. The
1104 column in index must be complete, or must contain a prefix longer than the
1105 column in index2. That is, we must be able to construct the prefix in index2
1106 from the prefix in index.
1107 @return position in internal representation of the index;
1108 ULINT_UNDEFINED if not contained */
1109 ulint
1110 dict_index_get_nth_field_pos(
1111 /*=========================*/
1112 	const dict_index_t*	index,	/*!< in: index from which to search */
1113 	const dict_index_t*	index2,	/*!< in: index */
1114 	ulint			n)	/*!< in: field number in index2 */
1115 	MY_ATTRIBUTE((nonnull, warn_unused_result));
1116 /********************************************************************//**
1117 Looks for column n position in the clustered index.
1118 @return position in internal representation of the clustered index */
1119 ulint
1120 dict_table_get_nth_col_pos(
1121 /*=======================*/
1122 	const dict_table_t*	table,	/*!< in: table */
1123 	ulint			n,	/*!< in: column number */
1124 	ulint*			prefix_col_pos) /*!< out: col num if prefix */
1125 	MY_ATTRIBUTE((nonnull(1), warn_unused_result));
1126 /*******************************************************************//**
1127 Adds a column to index. */
1128 void
1129 dict_index_add_col(
1130 /*===============*/
1131 	dict_index_t*		index,		/*!< in/out: index */
1132 	const dict_table_t*	table,		/*!< in: table */
1133 	dict_col_t*		col,		/*!< in: column */
1134 	ulint			prefix_len)	/*!< in: column prefix length */
1135 	MY_ATTRIBUTE((nonnull));
1136 
1137 /*******************************************************************//**
1138 Copies types of fields contained in index to tuple. */
1139 void
1140 dict_index_copy_types(
1141 /*==================*/
1142 	dtuple_t*		tuple,		/*!< in/out: data tuple */
1143 	const dict_index_t*	index,		/*!< in: index */
1144 	ulint			n_fields)	/*!< in: number of
1145 						field types to copy */
1146 	MY_ATTRIBUTE((nonnull));
1147 /*********************************************************************//**
1148 Gets the field column.
1149 @return field->col, pointer to the table column */
1150 UNIV_INLINE
1151 const dict_col_t*
1152 dict_field_get_col(
1153 /*===============*/
1154 	const dict_field_t*	field)	/*!< in: index field */
1155 	MY_ATTRIBUTE((nonnull, warn_unused_result));
1156 
1157 /**********************************************************************//**
1158 Returns an index object if it is found in the dictionary cache.
1159 Assumes that dict_sys.mutex is already being held.
1160 @return index, NULL if not found */
1161 dict_index_t*
1162 dict_index_get_if_in_cache_low(
1163 /*===========================*/
1164 	index_id_t	index_id)	/*!< in: index id */
1165 	MY_ATTRIBUTE((warn_unused_result));
1166 #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
1167 /**********************************************************************//**
1168 Returns an index object if it is found in the dictionary cache.
1169 @return index, NULL if not found */
1170 dict_index_t*
1171 dict_index_get_if_in_cache(
1172 /*=======================*/
1173 	index_id_t	index_id)	/*!< in: index id */
1174 	MY_ATTRIBUTE((warn_unused_result));
1175 #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
1176 #ifdef UNIV_DEBUG
1177 /**********************************************************************//**
1178 Checks that a tuple has n_fields_cmp value in a sensible range, so that
1179 no comparison can occur with the page number field in a node pointer.
1180 @return TRUE if ok */
1181 ibool
1182 dict_index_check_search_tuple(
1183 /*==========================*/
1184 	const dict_index_t*	index,	/*!< in: index tree */
1185 	const dtuple_t*		tuple)	/*!< in: tuple used in a search */
1186 	MY_ATTRIBUTE((nonnull, warn_unused_result));
1187 /** Whether and when to allow temporary index names */
1188 enum check_name {
1189 	/** Require all indexes to be complete. */
1190 	CHECK_ALL_COMPLETE,
1191 	/** Allow aborted online index creation. */
1192 	CHECK_ABORTED_OK,
1193 	/** Allow partial indexes to exist. */
1194 	CHECK_PARTIAL_OK
1195 };
1196 /**********************************************************************//**
1197 Check for duplicate index entries in a table [using the index name] */
1198 void
1199 dict_table_check_for_dup_indexes(
1200 /*=============================*/
1201 	const dict_table_t*	table,	/*!< in: Check for dup indexes
1202 					in this table */
1203 	enum check_name		check)	/*!< in: whether and when to allow
1204 					temporary index names */
1205 	MY_ATTRIBUTE((nonnull));
1206 #endif /* UNIV_DEBUG */
1207 /**********************************************************************//**
1208 Builds a node pointer out of a physical record and a page number.
1209 @return own: node pointer */
1210 dtuple_t*
1211 dict_index_build_node_ptr(
1212 /*======================*/
1213 	const dict_index_t*	index,	/*!< in: index */
1214 	const rec_t*		rec,	/*!< in: record for which to build node
1215 					pointer */
1216 	ulint			page_no,/*!< in: page number to put in node
1217 					pointer */
1218 	mem_heap_t*		heap,	/*!< in: memory heap where pointer
1219 					created */
1220 	ulint			level)	/*!< in: level of rec in tree:
1221 					0 means leaf level */
1222 	MY_ATTRIBUTE((nonnull, warn_unused_result));
1223 /** Convert a physical record into a search tuple.
1224 @param[in]	rec		index record (not necessarily in an index page)
1225 @param[in]	index		index
1226 @param[in]	leaf		whether rec is in a leaf page
1227 @param[in]	n_fields	number of data fields
1228 @param[in,out]	heap		memory heap for allocation
1229 @return own: data tuple */
1230 dtuple_t*
1231 dict_index_build_data_tuple(
1232 	const rec_t*		rec,
1233 	const dict_index_t*	index,
1234 	bool			leaf,
1235 	ulint			n_fields,
1236 	mem_heap_t*		heap)
1237 	MY_ATTRIBUTE((nonnull, warn_unused_result));
1238 
1239 /*********************************************************************//**
1240 Gets the page number of the root of the index tree.
1241 @return page number */
1242 UNIV_INLINE
1243 ulint
1244 dict_index_get_page(
1245 /*================*/
1246 	const dict_index_t*	tree)	/*!< in: index */
1247 	MY_ATTRIBUTE((nonnull, warn_unused_result));
1248 /*********************************************************************//**
1249 Gets the read-write lock of the index tree.
1250 @return read-write lock */
1251 UNIV_INLINE
1252 rw_lock_t*
1253 dict_index_get_lock(
1254 /*================*/
1255 	const dict_index_t*	index)	/*!< in: index */
1256 	MY_ATTRIBUTE((nonnull, warn_unused_result));
1257 /********************************************************************//**
1258 Returns free space reserved for future updates of records. This is
1259 relevant only in the case of many consecutive inserts, as updates
1260 which make the records bigger might fragment the index.
1261 @return number of free bytes on page, reserved for updates */
1262 UNIV_INLINE
1263 ulint
1264 dict_index_get_space_reserve(void);
1265 /*==============================*/
1266 
1267 /* Online index creation @{ */
1268 /********************************************************************//**
1269 Gets the status of online index creation.
1270 @return the status */
1271 UNIV_INLINE
1272 enum online_index_status
1273 dict_index_get_online_status(
1274 /*=========================*/
1275 	const dict_index_t*	index)	/*!< in: secondary index */
1276 	MY_ATTRIBUTE((nonnull, warn_unused_result));
1277 /********************************************************************//**
1278 Sets the status of online index creation. */
1279 UNIV_INLINE
1280 void
1281 dict_index_set_online_status(
1282 /*=========================*/
1283 	dict_index_t*			index,	/*!< in/out: index */
1284 	enum online_index_status	status)	/*!< in: status */
1285 	MY_ATTRIBUTE((nonnull));
1286 /********************************************************************//**
1287 Determines if a secondary index is being or has been created online,
1288 or if the table is being rebuilt online, allowing concurrent modifications
1289 to the table.
1290 @retval true if the index is being or has been built online, or
1291 if this is a clustered index and the table is being or has been rebuilt online
1292 @retval false if the index has been created or the table has been
1293 rebuilt completely */
1294 UNIV_INLINE
1295 bool
1296 dict_index_is_online_ddl(
1297 /*=====================*/
1298 	const dict_index_t*	index)	/*!< in: index */
1299 	MY_ATTRIBUTE((nonnull, warn_unused_result));
1300 /*********************************************************************//**
1301 Calculates the minimum record length in an index. */
1302 ulint
1303 dict_index_calc_min_rec_len(
1304 /*========================*/
1305 	const dict_index_t*	index)	/*!< in: index */
1306 	MY_ATTRIBUTE((nonnull, warn_unused_result));
1307 
1308 #define dict_mutex_enter_for_mysql() mutex_enter(&dict_sys.mutex)
1309 #define dict_mutex_exit_for_mysql() mutex_exit(&dict_sys.mutex)
1310 
1311 /********************************************************************//**
1312 Checks if the database name in two table names is the same.
1313 @return TRUE if same db name */
1314 ibool
1315 dict_tables_have_same_db(
1316 /*=====================*/
1317 	const char*	name1,	/*!< in: table name in the form
1318 				dbname '/' tablename */
1319 	const char*	name2)	/*!< in: table name in the form
1320 				dbname '/' tablename */
1321 	MY_ATTRIBUTE((nonnull, warn_unused_result));
1322 
1323 /** Get an index by name.
1324 @param[in]	table		the table where to look for the index
1325 @param[in]	name		the index name to look for
1326 @return index, NULL if does not exist */
1327 dict_index_t*
1328 dict_table_get_index_on_name(dict_table_t* table, const char* name)
1329 		MY_ATTRIBUTE((warn_unused_result));
1330 
1331 /** Get an index by name.
1332 @param[in]	table		the table where to look for the index
1333 @param[in]	name		the index name to look for
1334 @return index, NULL if does not exist */
1335 inline
1336 const dict_index_t*
dict_table_get_index_on_name(const dict_table_t * table,const char * name)1337 dict_table_get_index_on_name(const dict_table_t* table, const char* name)
1338 {
1339 	return dict_table_get_index_on_name(const_cast<dict_table_t*>(table),
1340 					    name);
1341 }
1342 
1343 /***************************************************************
1344 Check whether a column exists in an FTS index. */
1345 UNIV_INLINE
1346 ulint
1347 dict_table_is_fts_column(
1348 /*=====================*/
1349 				/* out: ULINT_UNDEFINED if no match else
1350 				the offset within the vector */
1351 	ib_vector_t*	indexes,/* in: vector containing only FTS indexes */
1352 	ulint		col_no,	/* in: col number to search for */
1353 	bool		is_virtual)/*!< in: whether it is a virtual column */
1354 	MY_ATTRIBUTE((warn_unused_result));
1355 
1356 /** Looks for an index with the given id given a table instance.
1357 @param[in]	table	table instance
1358 @param[in]	id	index id
1359 @return index or NULL */
1360 dict_index_t*
1361 dict_table_find_index_on_id(
1362 	const dict_table_t*	table,
1363 	index_id_t		id)
1364 	MY_ATTRIBUTE((nonnull(1)));
1365 
1366 /** Maximum number of columns in a foreign key constraint. Please Note MySQL
1367 has a much lower limit on the number of columns allowed in a foreign key
1368 constraint */
1369 #define MAX_NUM_FK_COLUMNS		500
1370 
1371 /* Buffers for storing detailed information about the latest foreign key
1372 and unique key errors */
1373 extern FILE*		dict_foreign_err_file;
1374 extern ib_mutex_t	dict_foreign_err_mutex; /* mutex protecting the
1375 						foreign key error messages */
1376 
1377 /** InnoDB data dictionary cache */
1378 class dict_sys_t
1379 {
1380 public:
1381 	DictSysMutex	mutex;		/*!< mutex protecting the data
1382 					dictionary; protects also the
1383 					disk-based dictionary system tables;
1384 					this mutex serializes CREATE TABLE
1385 					and DROP TABLE, as well as reading
1386 					the dictionary data for a table from
1387 					system tables */
1388 	/** @brief the data dictionary rw-latch protecting dict_sys
1389 
1390 	Table create, drop, etc. reserve this in X-mode; implicit or
1391 	backround operations purge, rollback, foreign key checks reserve this
1392 	in S-mode; not all internal InnoDB operations are covered by MDL.
1393 
1394 	This latch also prevents lock waits when accessing the InnoDB
1395 	data dictionary tables. @see trx_t::dict_operation_lock_mode */
1396 	rw_lock_t	latch;
1397 	row_id_t	row_id;		/*!< the next row id to assign;
1398 					NOTE that at a checkpoint this
1399 					must be written to the dict system
1400 					header and flushed to a file; in
1401 					recovery this must be derived from
1402 					the log records */
1403 	hash_table_t*	table_hash;	/*!< hash table of the tables, based
1404 					on name */
1405 	/** hash table of persistent table IDs */
1406 	hash_table_t*	table_id_hash;
1407 	dict_table_t*	sys_tables;	/*!< SYS_TABLES table */
1408 	dict_table_t*	sys_columns;	/*!< SYS_COLUMNS table */
1409 	dict_table_t*	sys_indexes;	/*!< SYS_INDEXES table */
1410 	dict_table_t*	sys_fields;	/*!< SYS_FIELDS table */
1411 	dict_table_t*	sys_virtual;	/*!< SYS_VIRTUAL table */
1412 
1413 	/*=============================*/
1414 	UT_LIST_BASE_NODE_T(dict_table_t)
1415 			table_LRU;	/*!< List of tables that can be evicted
1416 					from the cache */
1417 	UT_LIST_BASE_NODE_T(dict_table_t)
1418 			table_non_LRU;	/*!< List of tables that can't be
1419 					evicted from the cache */
1420 private:
1421 	bool m_initialised;
1422 	/** the sequence of temporary table IDs */
1423 	std::atomic<table_id_t> temp_table_id;
1424 	/** hash table of temporary table IDs */
1425 	hash_table_t*	temp_id_hash;
1426 public:
1427 	/** @return a new temporary table ID */
get_temporary_table_id()1428 	table_id_t get_temporary_table_id() {
1429 		return temp_table_id.fetch_add(1, std::memory_order_relaxed);
1430 	}
1431 
1432 	/** Look up a temporary table.
1433 	@param id	temporary table ID
1434 	@return	temporary table
1435 	@retval	NULL	if the table does not exist
1436 	(should only happen during the rollback of CREATE...SELECT) */
get_temporary_table(table_id_t id)1437 	dict_table_t* get_temporary_table(table_id_t id)
1438 	{
1439 		ut_ad(mutex_own(&mutex));
1440 		dict_table_t* table;
1441 		ulint fold = ut_fold_ull(id);
1442 		HASH_SEARCH(id_hash, temp_id_hash, fold, dict_table_t*, table,
1443 			    ut_ad(table->cached), table->id == id);
1444 		if (UNIV_LIKELY(table != NULL)) {
1445 			DBUG_ASSERT(table->is_temporary());
1446 			DBUG_ASSERT(table->id >= DICT_HDR_FIRST_ID);
1447 			table->acquire();
1448 		}
1449 		return table;
1450 	}
1451 
1452 	/** Look up a persistent table.
1453 	@param id	table ID
1454 	@return	table
1455 	@retval	NULL	if not cached */
get_table(table_id_t id)1456 	dict_table_t* get_table(table_id_t id)
1457 	{
1458 		ut_ad(mutex_own(&mutex));
1459 		dict_table_t* table;
1460 		ulint fold = ut_fold_ull(id);
1461 		HASH_SEARCH(id_hash, table_id_hash, fold, dict_table_t*, table,
1462 			    ut_ad(table->cached), table->id == id);
1463 		DBUG_ASSERT(!table || !table->is_temporary());
1464 		return table;
1465 	}
1466 
1467   /**
1468     Constructor.  Further initialisation happens in create().
1469   */
1470 
dict_sys_t()1471   dict_sys_t() : m_initialised(false), temp_table_id(DICT_HDR_FIRST_ID) {}
1472 
is_initialised()1473   bool is_initialised() const { return m_initialised; }
1474 
1475   /** Initialise the data dictionary cache. */
1476   void create();
1477 
1478   /** Close the data dictionary cache on shutdown. */
1479   void close();
1480 
1481   /** Resize the hash tables based on the current buffer pool size. */
1482   void resize();
1483 
1484   /** Add a table definition to the data dictionary cache */
1485   inline void add(dict_table_t* table);
1486   /** Remove a table definition from the data dictionary cache.
1487   @param[in,out]	table	cached table definition to be evicted
1488   @param[in]	lru	whether this is part of least-recently-used evictiono
1489   @param[in]	keep	whether to keep (not free) the object */
1490   void remove(dict_table_t* table, bool lru = false, bool keep = false);
1491 
1492 #ifdef UNIV_DEBUG
1493   /** Find a table */
find(dict_table_t * table)1494   template <bool in_lru> bool find(dict_table_t* table)
1495   {
1496     ut_ad(table);
1497     ut_ad(table->can_be_evicted == in_lru);
1498     ut_ad(mutex_own(&mutex));
1499     for (const dict_table_t* t = UT_LIST_GET_FIRST(in_lru
1500 					     ? table_LRU : table_non_LRU);
1501 	 t; t = UT_LIST_GET_NEXT(table_LRU, t))
1502     {
1503       if (t == table) return true;
1504       ut_ad(t->can_be_evicted == in_lru);
1505     }
1506     return false;
1507   }
1508   /** Find a table */
find(dict_table_t * table)1509   bool find(dict_table_t* table)
1510   {
1511     return table->can_be_evicted ? find<true>(table) : find<false>(table);
1512   }
1513 #endif
1514 
1515   /** Move a table to the non-LRU list from the LRU list. */
prevent_eviction(dict_table_t * table)1516   void prevent_eviction(dict_table_t* table)
1517   {
1518     ut_ad(find(table));
1519     if (table->can_be_evicted)
1520     {
1521       table->can_be_evicted = FALSE;
1522       UT_LIST_REMOVE(table_LRU, table);
1523       UT_LIST_ADD_LAST(table_non_LRU, table);
1524     }
1525   }
1526   /** Acquire a reference to a cached table. */
1527   inline void acquire(dict_table_t* table);
1528 
1529 #ifdef UNIV_DEBUG
1530   /** Assert that the data dictionary is locked */
assert_locked()1531   void assert_locked()
1532   {
1533     ut_ad(mutex_own(&mutex));
1534     ut_ad(rw_lock_own(&latch, RW_LOCK_X));
1535   }
1536 #endif
1537   /** Lock the data dictionary cache. */
lock(const char * file,unsigned line)1538   void lock(const char* file, unsigned line)
1539   {
1540     rw_lock_x_lock_func(&latch, 0, file, line);
1541     mutex_enter_loc(&mutex, file, line);
1542   }
1543 
1544   /** Unlock the data dictionary cache. */
unlock()1545   void unlock()
1546   {
1547     mutex_exit(&mutex);
1548     rw_lock_x_unlock(&latch);
1549   }
1550 };
1551 
1552 /** the data dictionary cache */
1553 extern dict_sys_t	dict_sys;
1554 
1555 #define dict_table_prevent_eviction(table) dict_sys.prevent_eviction(table)
1556 #define dict_sys_lock() dict_sys.lock(__FILE__, __LINE__)
1557 #define dict_sys_unlock() dict_sys.unlock()
1558 
1559 /** dummy index for ROW_FORMAT=REDUNDANT supremum and infimum records */
1560 extern dict_index_t*	dict_ind_redundant;
1561 
1562 /** Initialize dict_ind_redundant. */
1563 void
1564 dict_ind_init();
1565 
1566 /** Free dict_ind_redundant. */
1567 void
1568 dict_ind_free();
1569 
1570 /* Auxiliary structs for checking a table definition @{ */
1571 
1572 /* This struct is used to specify the name and type that a column must
1573 have when checking a table's schema. */
1574 struct dict_col_meta_t {
1575 	const char*	name;		/* column name */
1576 	ulint		mtype;		/* required column main type */
1577 	ulint		prtype_mask;	/* required column precise type mask;
1578 					if this is non-zero then all the
1579 					bits it has set must also be set
1580 					in the column's prtype */
1581 	ulint		len;		/* required column length */
1582 };
1583 
1584 /* This struct is used for checking whether a given table exists and
1585 whether it has a predefined schema (number of columns and column names
1586 and types) */
1587 struct dict_table_schema_t {
1588 	const char*		table_name;	/* the name of the table whose
1589 						structure we are checking */
1590 	ulint			n_cols;		/* the number of columns the
1591 						table must have */
1592 	dict_col_meta_t*	columns;	/* metadata for the columns;
1593 						this array has n_cols
1594 						elements */
1595 	ulint			n_foreign;	/* number of foreign keys this
1596 						table has, pointing to other
1597 						tables (where this table is
1598 						FK child) */
1599 	ulint			n_referenced;	/* number of foreign keys other
1600 						tables have, pointing to this
1601 						table (where this table is
1602 						parent) */
1603 };
1604 /* @} */
1605 
1606 /*********************************************************************//**
1607 Checks whether a table exists and whether it has the given structure.
1608 The table must have the same number of columns with the same names and
1609 types. The order of the columns does not matter.
1610 The caller must own the dictionary mutex.
1611 dict_table_schema_check() @{
1612 @return DB_SUCCESS if the table exists and contains the necessary columns */
1613 dberr_t
1614 dict_table_schema_check(
1615 /*====================*/
1616 	dict_table_schema_t*	req_schema,	/*!< in/out: required table
1617 						schema */
1618 	char*			errstr,		/*!< out: human readable error
1619 						message if != DB_SUCCESS and
1620 						!= DB_TABLE_NOT_FOUND is
1621 						returned */
1622 	size_t			errstr_sz)	/*!< in: errstr size */
1623 	MY_ATTRIBUTE((nonnull, warn_unused_result));
1624 /* @} */
1625 
1626 /*********************************************************************//**
1627 Converts a database and table name from filesystem encoding
1628 (e.g. d@i1b/a@q1b@1Kc, same format as used in dict_table_t::name) in two
1629 strings in UTF8 encoding (e.g. dцb and aюbØc). The output buffers must be
1630 at least MAX_DB_UTF8_LEN and MAX_TABLE_UTF8_LEN bytes. */
1631 void
1632 dict_fs2utf8(
1633 /*=========*/
1634 	const char*	db_and_table,	/*!< in: database and table names,
1635 					e.g. d@i1b/a@q1b@1Kc */
1636 	char*		db_utf8,	/*!< out: database name, e.g. dцb */
1637 	size_t		db_utf8_size,	/*!< in: dbname_utf8 size */
1638 	char*		table_utf8,	/*!< out: table name, e.g. aюbØc */
1639 	size_t		table_utf8_size)/*!< in: table_utf8 size */
1640 	MY_ATTRIBUTE((nonnull));
1641 
1642 /**********************************************************************//**
1643 Check whether the table is corrupted.
1644 @return nonzero for corrupted table, zero for valid tables */
1645 UNIV_INLINE
1646 ulint
1647 dict_table_is_corrupted(
1648 /*====================*/
1649 	const dict_table_t*	table)	/*!< in: table */
1650 	MY_ATTRIBUTE((nonnull, warn_unused_result));
1651 
1652 /**********************************************************************//**
1653 Flags an index and table corrupted both in the data dictionary cache
1654 and in the system table SYS_INDEXES. */
1655 void
1656 dict_set_corrupted(
1657 /*===============*/
1658 	dict_index_t*	index,	/*!< in/out: index */
1659 	trx_t*		trx,	/*!< in/out: transaction */
1660 	const char*	ctx)	/*!< in: context */
1661 	ATTRIBUTE_COLD __attribute__((nonnull));
1662 
1663 /** Flags an index corrupted in the data dictionary cache only. This
1664 is used mostly to mark a corrupted index when index's own dictionary
1665 is corrupted, and we force to load such index for repair purpose
1666 @param[in,out]	index	index that is corrupted */
1667 void
1668 dict_set_corrupted_index_cache_only(
1669 	dict_index_t*	index);
1670 
1671 /**********************************************************************//**
1672 Flags a table with specified space_id corrupted in the table dictionary
1673 cache.
1674 @return TRUE if successful */
1675 bool dict_set_corrupted_by_space(const fil_space_t* space);
1676 
1677 /** Flag a table encrypted in the data dictionary cache. */
1678 void dict_set_encrypted_by_space(const fil_space_t* space);
1679 
1680 /** Sets merge_threshold in the SYS_INDEXES
1681 @param[in,out]	index		index
1682 @param[in]	merge_threshold	value to set */
1683 void
1684 dict_index_set_merge_threshold(
1685 	dict_index_t*	index,
1686 	ulint		merge_threshold);
1687 
1688 #ifdef UNIV_DEBUG
1689 /** Sets merge_threshold for all indexes in dictionary cache for debug.
1690 @param[in]	merge_threshold_all	value to set for all indexes */
1691 void
1692 dict_set_merge_threshold_all_debug(
1693 	uint	merge_threshold_all);
1694 #endif /* UNIV_DEBUG */
1695 
1696 /** Validate the table flags.
1697 @param[in]	flags	Table flags
1698 @return true if valid. */
1699 UNIV_INLINE
1700 bool
1701 dict_tf_is_valid(
1702 	ulint	flags);
1703 
1704 /** Validate both table flags and table flags2 and make sure they
1705 are compatible.
1706 @param[in]	flags	Table flags
1707 @param[in]	flags2	Table flags2
1708 @return true if valid. */
1709 UNIV_INLINE
1710 bool
1711 dict_tf2_is_valid(
1712 	ulint	flags,
1713 	ulint	flags2);
1714 
1715 /*********************************************************************//**
1716 This function should be called whenever a page is successfully
1717 compressed. Updates the compression padding information. */
1718 void
1719 dict_index_zip_success(
1720 /*===================*/
1721 	dict_index_t*	index)	/*!< in/out: index to be updated. */
1722 	MY_ATTRIBUTE((nonnull));
1723 /*********************************************************************//**
1724 This function should be called whenever a page compression attempt
1725 fails. Updates the compression padding information. */
1726 void
1727 dict_index_zip_failure(
1728 /*===================*/
1729 	dict_index_t*	index)	/*!< in/out: index to be updated. */
1730 	MY_ATTRIBUTE((nonnull));
1731 /*********************************************************************//**
1732 Return the optimal page size, for which page will likely compress.
1733 @return page size beyond which page may not compress*/
1734 ulint
1735 dict_index_zip_pad_optimal_page_size(
1736 /*=================================*/
1737 	dict_index_t*	index)	/*!< in: index for which page size
1738 				is requested */
1739 	MY_ATTRIBUTE((nonnull, warn_unused_result));
1740 /*************************************************************//**
1741 Convert table flag to row format string.
1742 @return row format name */
1743 const char*
1744 dict_tf_to_row_format_string(
1745 /*=========================*/
1746 	ulint	table_flag);		/*!< in: row format setting */
1747 
1748 /** encode number of columns and number of virtual columns in one
1749 4 bytes value. We could do this because the number of columns in
1750 InnoDB is limited to 1017
1751 @param[in]	n_col	number of non-virtual column
1752 @param[in]	n_v_col	number of virtual column
1753 @return encoded value */
1754 UNIV_INLINE
1755 ulint
1756 dict_table_encode_n_col(
1757 	ulint	n_col,
1758 	ulint	n_v_col);
1759 
1760 /** Decode number of virtual and non-virtual columns in one 4 bytes value.
1761 @param[in]	encoded	encoded value
1762 @param[in,out]	n_col	number of non-virtual column
1763 @param[in,out]	n_v_col	number of virtual column */
1764 UNIV_INLINE
1765 void
1766 dict_table_decode_n_col(
1767 	ulint	encoded,
1768 	ulint*	n_col,
1769 	ulint*	n_v_col);
1770 
1771 /** Calculate the used memory occupied by the data dictionary
1772 table and index objects.
1773 @return number of bytes occupied. */
1774 UNIV_INTERN
1775 ulint
1776 dict_sys_get_size();
1777 
1778 /** Free the virtual column template
1779 @param[in,out]	vc_templ	virtual column template */
1780 UNIV_INLINE
1781 void
1782 dict_free_vc_templ(
1783 	dict_vcol_templ_t*	vc_templ);
1784 
1785 /** Check whether the table have virtual index.
1786 @param[in]	table	InnoDB table
1787 @return true if the table have virtual index, false otherwise. */
1788 UNIV_INLINE
1789 bool
1790 dict_table_have_virtual_index(
1791 	dict_table_t*	table);
1792 
1793 #include "dict0dict.inl"
1794 
1795 #endif
1796