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