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