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