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