1 /***************************************************************************** 2 3 Copyright (c) 1996, 2020, Oracle and/or its affiliates. All Rights Reserved. 4 Copyright (c) 2012, Facebook Inc. 5 6 This program is free software; you can redistribute it and/or modify it under 7 the terms of the GNU General Public License, version 2.0, as published by the 8 Free Software Foundation. 9 10 This program is also distributed with certain software (including but not 11 limited to OpenSSL) that is licensed under separate terms, as designated in a 12 particular file or component or in included license documentation. The authors 13 of MySQL hereby grant you an additional permission to link the program and 14 your derivative works with the separately licensed software that they have 15 included with MySQL. 16 17 This program is distributed in the hope that it will be useful, but WITHOUT 18 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 19 FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0, 20 for more details. 21 22 You should have received a copy of the GNU General Public License along with 23 this program; if not, write to the Free Software Foundation, Inc., 24 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 25 26 *****************************************************************************/ 27 28 /** @file include/dict0dict.h 29 Data dictionary system 30 31 Created 1/8/1996 Heikki Tuuri 32 *******************************************************/ 33 34 #ifndef dict0dict_h 35 #define dict0dict_h 36 37 #include <set> 38 39 #include <deque> 40 #include "data0data.h" 41 #include "data0type.h" 42 #include "dict/dict.h" 43 #include "dict0mem.h" 44 #include "dict0types.h" 45 #include "fsp0fsp.h" 46 #include "fsp0sysspace.h" 47 #include "hash0hash.h" 48 #include "mem0mem.h" 49 #include "rem0types.h" 50 #include "row0types.h" 51 #include "sql/dd/object_id.h" 52 #include "sync0rw.h" 53 #include "trx0types.h" 54 #include "univ.i" 55 #include "ut0byte.h" 56 #include "ut0mem.h" 57 #include "ut0new.h" 58 #include "ut0rnd.h" 59 60 #define DICT_HEAP_SIZE \ 61 100 /*!< initial memory heap size when \ 62 creating a table or index object */ 63 64 /** SDI version. Written on Page 1 & 2 at FIL_PAGE_FILE_FLUSH_LSN offset. */ 65 const uint32_t SDI_VERSION = 1; 66 67 /** Space id of system tablespace */ 68 const space_id_t SYSTEM_TABLE_SPACE = TRX_SYS_SPACE; 69 70 /** Get the database name length in a table name. 71 @return database name length */ 72 ulint dict_get_db_name_len(const char *name) /*!< in: table name in the form 73 dbname '/' tablename */ 74 MY_ATTRIBUTE((warn_unused_result)); 75 #ifndef UNIV_HOTBACKUP 76 /** Frees a foreign key struct. */ 77 void dict_foreign_free( 78 dict_foreign_t *foreign); /*!< in, own: foreign key struct */ 79 /** Finds the highest [number] for foreign key constraints of the table. Looks 80 only at the >= 4.0.18-format id's, which are of the form 81 databasename/tablename_ibfk_[number]. 82 @return highest number, 0 if table has no new format foreign key constraints */ 83 ulint dict_table_get_highest_foreign_id( 84 dict_table_t *table); /*!< in: table in the dictionary 85 memory cache */ 86 #endif /* !UNIV_HOTBACKUP */ 87 /** Return the end of table name where we have removed dbname and '/'. 88 @return table name */ 89 const char *dict_remove_db_name(const char *name) /*!< in: table name in the 90 form dbname '/' tablename */ 91 MY_ATTRIBUTE((warn_unused_result)); 92 93 /** Operation to perform when opening a table */ 94 enum dict_table_op_t { 95 /** Expect the tablespace to exist. */ 96 DICT_TABLE_OP_NORMAL = 0, 97 /** Drop any orphan indexes after an aborted online index creation */ 98 DICT_TABLE_OP_DROP_ORPHAN, 99 /** Silently load the tablespace if it does not exist, 100 and do not load the definitions of incomplete indexes. */ 101 DICT_TABLE_OP_LOAD_TABLESPACE 102 }; 103 104 /** Decrements the count of open handles to a table. */ 105 void dict_table_close(dict_table_t *table, /*!< in/out: table */ 106 ibool dict_locked, /*!< in: TRUE=data dictionary locked */ 107 ibool try_drop); /*!< in: TRUE=try to drop any orphan 108 indexes after an aborted online 109 index creation */ 110 /** Closes the only open handle to a table and drops a table while assuring 111 that dict_sys->mutex is held the whole time. This assures that the table 112 is not evicted after the close when the count of open handles goes to zero. 113 Because dict_sys->mutex is held, we do not need to call 114 dict_table_prevent_eviction(). */ 115 void dict_table_close_and_drop( 116 trx_t *trx, /*!< in: data dictionary transaction */ 117 dict_table_t *table); /*!< in/out: table */ 118 /** Inits the data dictionary module. */ 119 void dict_init(void); 120 121 /** Closes the data dictionary module. */ 122 void dict_close(void); 123 124 /** Inits the structure for persisting dynamic metadata */ 125 void dict_persist_init(void); 126 127 /** Clear the structure */ 128 void dict_persist_close(void); 129 130 #ifndef UNIV_HOTBACKUP 131 /** Write back the dirty persistent dynamic metadata of the table 132 to DDTableBuffer. 133 @param[in,out] table table object */ 134 void dict_table_persist_to_dd_table_buffer(dict_table_t *table); 135 136 /** Read persistent dynamic metadata stored in a buffer 137 @param[in] buffer buffer to read 138 @param[in] size size of data in buffer 139 @param[in] metadata where we store the metadata from buffer */ 140 void dict_table_read_dynamic_metadata(const byte *buffer, ulint size, 141 PersistentTableMetadata *metadata); 142 143 /** Determine bytes of column prefix to be stored in the undo log. Please 144 note that if !dict_table_has_atomic_blobs(table), no prefix 145 needs to be stored in the undo log. 146 @return bytes of column prefix to be stored in the undo log */ 147 UNIV_INLINE 148 ulint dict_max_field_len_store_undo( 149 dict_table_t *table, /*!< in: table */ 150 const dict_col_t *col) /*!< in: column which index prefix 151 is based on */ 152 MY_ATTRIBUTE((warn_unused_result)); 153 154 /** Determine maximum bytes of a virtual column need to be stored 155 in the undo log. 156 @param[in] table dict_table_t for the table 157 @param[in] col_no virtual column number 158 @return maximum bytes of virtual column to be stored in the undo log */ 159 UNIV_INLINE 160 ulint dict_max_v_field_len_store_undo(dict_table_t *table, ulint col_no); 161 162 #endif /* !UNIV_HOTBACKUP */ 163 /** Gets the column number. 164 @return col->ind, table column position (starting from 0) */ 165 UNIV_INLINE 166 ulint dict_col_get_no(const dict_col_t *col) /*!< in: column */ 167 MY_ATTRIBUTE((warn_unused_result)); 168 /** Gets the column position in the clustered index. */ 169 UNIV_INLINE 170 ulint dict_col_get_clust_pos( 171 const dict_col_t *col, /*!< in: table column */ 172 const dict_index_t *clust_index) /*!< in: clustered index */ 173 MY_ATTRIBUTE((warn_unused_result)); 174 175 #ifndef UNIV_HOTBACKUP 176 /** Gets the column position in the given index. 177 @param[in] col table column 178 @param[in] index index to be searched for column 179 @return position of column in the given index. */ 180 UNIV_INLINE 181 ulint dict_col_get_index_pos(const dict_col_t *col, const dict_index_t *index) 182 MY_ATTRIBUTE((nonnull, warn_unused_result)); 183 184 /** If the given column name is reserved for InnoDB system columns, return 185 TRUE. 186 @return true if name is reserved */ 187 ibool dict_col_name_is_reserved(const char *name) /*!< in: column name */ 188 MY_ATTRIBUTE((warn_unused_result)); 189 /** Acquire the autoinc lock. */ 190 void dict_table_autoinc_lock(dict_table_t *table); /*!< in/out: table */ 191 192 /** Unconditionally set the autoinc counter. */ 193 void dict_table_autoinc_initialize( 194 dict_table_t *table, /*!< in/out: table */ 195 ib_uint64_t value); /*!< in: next value to assign to a row */ 196 /** Reads the next autoinc value (== autoinc counter value), 0 if not yet 197 initialized. 198 @return value for a new row, or 0 */ 199 ib_uint64_t dict_table_autoinc_read(const dict_table_t *table) /*!< in: table */ 200 MY_ATTRIBUTE((warn_unused_result)); 201 /** Updates the autoinc counter if the value supplied is greater than the 202 current value. */ 203 void dict_table_autoinc_update_if_greater( 204 205 dict_table_t *table, /*!< in/out: table */ 206 ib_uint64_t value); /*!< in: value which was assigned to a row */ 207 /** Release the autoinc lock. */ 208 void dict_table_autoinc_unlock(dict_table_t *table); /*!< in/out: table */ 209 210 /** Update the persisted autoinc counter to specified one, we should hold 211 autoinc_persisted_mutex. 212 @param[in,out] table table 213 @param[in] autoinc set autoinc_persisted to this value */ 214 UNIV_INLINE 215 void dict_table_autoinc_persisted_update(dict_table_t *table, 216 ib_uint64_t autoinc); 217 218 /** Set the column position of autoinc column in clustered index for a table. 219 @param[in] table table 220 @param[in] pos column position in table definition */ 221 UNIV_INLINE 222 void dict_table_autoinc_set_col_pos(dict_table_t *table, ulint pos); 223 224 /** Write redo logs for autoinc counter that is to be inserted, or to 225 update some existing smaller one to bigger. 226 @param[in,out] table InnoDB table object 227 @param[in] value AUTOINC counter to log 228 @param[in,out] mtr mini-transaction */ 229 void dict_table_autoinc_log(dict_table_t *table, uint64_t value, mtr_t *mtr); 230 231 /** Check if a table has an autoinc counter column. 232 @param[in] table table 233 @return true if there is an autoinc column in the table, otherwise false. */ 234 UNIV_INLINE 235 bool dict_table_has_autoinc_col(const dict_table_t *table); 236 237 #endif /* !UNIV_HOTBACKUP */ 238 /** Adds system columns to a table object. */ 239 void dict_table_add_system_columns(dict_table_t *table, /*!< in/out: table */ 240 mem_heap_t *heap); /*!< in: temporary heap */ 241 #ifndef UNIV_HOTBACKUP 242 /** Mark if table has big rows. 243 @param[in,out] table table handler */ 244 void dict_table_set_big_rows(dict_table_t *table) MY_ATTRIBUTE((nonnull)); 245 /** Adds a table object to the dictionary cache. 246 @param[in] table table 247 @param[in] can_be_evicted true if can be evicted 248 @param[in] heap temporary heap 249 */ 250 void dict_table_add_to_cache(dict_table_t *table, ibool can_be_evicted, 251 mem_heap_t *heap); 252 253 /** Removes a table object from the dictionary cache. */ 254 void dict_table_remove_from_cache(dict_table_t *table); /*!< in, own: table */ 255 256 /** Try to invalidate an entry from the dict cache, for a partitioned table, 257 if any table found. 258 @param[in] name Table name */ 259 void dict_partitioned_table_remove_from_cache(const char *name); 260 261 #ifdef UNIV_DEBUG 262 /** Removes a table object from the dictionary cache, for debug purpose 263 @param[in,out] table table object 264 @param[in] lru_evict true if table being evicted to make room 265 in the table LRU list */ 266 void dict_table_remove_from_cache_debug(dict_table_t *table, bool lru_evict); 267 #endif /* UNIV_DEBUG */ 268 269 /** Renames a table object. 270 @return true if success */ 271 dberr_t dict_table_rename_in_cache(dict_table_t *table, /*!< in/out: table */ 272 const char *new_name, /*!< in: new name */ 273 ibool rename_also_foreigns) 274 /*!< in: in ALTER TABLE we want 275 to preserve the original table name 276 in constraints which reference it */ 277 MY_ATTRIBUTE((warn_unused_result)); 278 279 /** Removes an index from the dictionary cache. 280 @param[in,out] table table whose index to remove 281 @param[in,out] index index to remove, this object is destroyed and must not 282 be accessed by the caller afterwards */ 283 void dict_index_remove_from_cache(dict_table_t *table, dict_index_t *index); 284 285 /** Change the id of a table object in the dictionary cache. This is used in 286 DISCARD TABLESPACE. */ 287 void dict_table_change_id_in_cache( 288 dict_table_t *table, /*!< in/out: table object already in cache */ 289 table_id_t new_id); /*!< in: new id to set */ 290 /** Removes a foreign constraint struct from the dictionary cache. */ 291 void dict_foreign_remove_from_cache( 292 dict_foreign_t *foreign); /*!< in, own: foreign constraint */ 293 /** Adds a foreign key constraint object to the dictionary cache. May free 294 the object if there already is an object with the same identifier in. 295 At least one of foreign table or referenced table must already be in 296 the dictionary cache! 297 @return DB_SUCCESS or error code */ 298 dberr_t dict_foreign_add_to_cache(dict_foreign_t *foreign, 299 /*!< in, own: foreign key constraint */ 300 const char **col_names, 301 /*!< in: column names, or NULL to use 302 foreign->foreign_table->col_names */ 303 bool check_charsets, 304 /*!< in: whether to check charset 305 compatibility */ 306 bool can_free_fk, 307 /*!< in: whether free existing FK */ 308 dict_err_ignore_t ignore_err) 309 /*!< in: error to be ignored */ 310 MY_ATTRIBUTE((warn_unused_result)); 311 /** Checks if a table is referenced by foreign keys. 312 @return true if table is referenced by a foreign key */ 313 ibool dict_table_is_referenced_by_foreign_key( 314 const dict_table_t *table) /*!< in: InnoDB table */ 315 MY_ATTRIBUTE((warn_unused_result)); 316 /** Replace the index passed in with another equivalent index in the 317 foreign key lists of the table. 318 @return whether all replacements were found */ 319 bool dict_foreign_replace_index( 320 dict_table_t *table, /*!< in/out: table */ 321 const char **col_names, 322 /*!< in: column names, or NULL 323 to use table->col_names */ 324 const dict_index_t *index) /*!< in: index to be replaced */ 325 MY_ATTRIBUTE((warn_unused_result)); 326 #endif /* !UNIV_HOTBACKUP */ 327 /** Returns a table object and increments its open handle count. 328 NOTE! This is a high-level function to be used mainly from outside the 329 'dict' directory. Inside this directory dict_table_get_low 330 is usually the appropriate function. 331 @param[in] table_name Table name 332 @param[in] dict_locked TRUE=data dictionary locked 333 @param[in] try_drop TRUE=try to drop any orphan indexes after 334 an aborted online index creation 335 @param[in] ignore_err error to be ignored when loading the table 336 @return table, NULL if does not exist */ 337 dict_table_t *dict_table_open_on_name(const char *table_name, ibool dict_locked, 338 ibool try_drop, 339 dict_err_ignore_t ignore_err) 340 MY_ATTRIBUTE((warn_unused_result)); 341 342 /** Tries to find an index whose first fields are the columns in the array, 343 in the same order and is not marked for deletion and is not the same 344 as types_idx. 345 @return matching index, NULL if not found */ 346 dict_index_t *dict_foreign_find_index( 347 const dict_table_t *table, /*!< in: table */ 348 const char **col_names, 349 /*!< in: column names, or NULL 350 to use table->col_names */ 351 const char **columns, /*!< in: array of column names */ 352 ulint n_cols, /*!< in: number of columns */ 353 const dict_index_t *types_idx, 354 /*!< in: NULL or an index 355 whose types the column types 356 must match */ 357 bool check_charsets, 358 /*!< in: whether to check 359 charsets. only has an effect 360 if types_idx != NULL */ 361 ulint check_null) 362 /*!< in: nonzero if none of 363 the columns must be declared 364 NOT NULL */ 365 MY_ATTRIBUTE((warn_unused_result)); 366 367 /** Returns a virtual column's name. 368 @param[in] table table object 369 @param[in] col_nr virtual column number(nth virtual column) 370 @return column name. */ 371 const char *dict_table_get_v_col_name(const dict_table_t *table, ulint col_nr); 372 373 /** Check if the table has a given column. 374 @param[in] table table object 375 @param[in] col_name column name 376 @param[in] col_nr column number guessed, 0 as default 377 @return column number if the table has the specified column, 378 otherwise table->n_def */ 379 ulint dict_table_has_column(const dict_table_t *table, const char *col_name, 380 ulint col_nr = 0); 381 382 /** Outputs info on a foreign key of a table in a format suitable for 383 CREATE TABLE. */ 384 void dict_print_info_on_foreign_key_in_create_format( 385 FILE *file, /*!< in: file where to print */ 386 trx_t *trx, /*!< in: transaction */ 387 dict_foreign_t *foreign, /*!< in: foreign key constraint */ 388 ibool add_newline); /*!< in: whether to add a newline */ 389 /** Tries to find an index whose first fields are the columns in the array, 390 in the same order and is not marked for deletion and is not the same 391 as types_idx. 392 @return matching index, NULL if not found */ 393 bool dict_foreign_qualify_index( 394 const dict_table_t *table, /*!< in: table */ 395 const char **col_names, 396 /*!< in: column names, or NULL 397 to use table->col_names */ 398 const char **columns, /*!< in: array of column names */ 399 ulint n_cols, /*!< in: number of columns */ 400 const dict_index_t *index, /*!< in: index to check */ 401 const dict_index_t *types_idx, 402 /*!< in: NULL or an index 403 whose types the column types 404 must match */ 405 bool check_charsets, 406 /*!< in: whether to check 407 charsets. only has an effect 408 if types_idx != NULL */ 409 ulint check_null) 410 /*!< in: nonzero if none of 411 the columns must be declared 412 NOT NULL */ 413 MY_ATTRIBUTE((warn_unused_result)); 414 415 /* Skip corrupted index */ 416 #define dict_table_skip_corrupt_index(index) \ 417 while (index && index->is_corrupted()) { \ 418 index = index->next(); \ 419 } 420 421 /* Get the next non-corrupt index */ 422 #define dict_table_next_uncorrupted_index(index) \ 423 do { \ 424 index = index->next(); \ 425 dict_table_skip_corrupt_index(index); \ 426 } while (0) 427 428 /** Check if index is auto-generated clustered index. 429 @param[in] index index 430 431 @return true if index is auto-generated clustered index. */ 432 UNIV_INLINE 433 bool dict_index_is_auto_gen_clust(const dict_index_t *index); 434 435 /** Check whether the index is unique. 436 @return nonzero for unique index, zero for other indexes */ 437 UNIV_INLINE 438 ulint dict_index_is_unique(const dict_index_t *index) /*!< in: index */ 439 MY_ATTRIBUTE((warn_unused_result)); 440 /** Check whether the index is a Spatial Index. 441 @return nonzero for Spatial Index, zero for other indexes */ 442 UNIV_INLINE 443 ulint dict_index_is_spatial(const dict_index_t *index) /*!< in: index */ 444 MY_ATTRIBUTE((warn_unused_result)); 445 /** Check whether the index contains a virtual column. 446 @param[in] index index 447 @return nonzero for index on virtual column, zero for other indexes */ 448 UNIV_INLINE 449 ulint dict_index_has_virtual(const dict_index_t *index); 450 /** Check whether the index is the insert buffer tree. 451 @return nonzero for insert buffer, zero for other indexes */ 452 UNIV_INLINE 453 ulint dict_index_is_ibuf(const dict_index_t *index) /*!< in: index */ 454 MY_ATTRIBUTE((warn_unused_result)); 455 456 /** Check whether the index consists of descending columns only. 457 @param[in] index index tree 458 @retval true if index has any descending column 459 @retval false if index has only ascending columns */ 460 UNIV_INLINE 461 bool dict_index_has_desc(const dict_index_t *index) 462 MY_ATTRIBUTE((warn_unused_result)); 463 /** Check whether the index is a secondary index or the insert buffer tree. 464 @return nonzero for insert buffer, zero for other indexes */ 465 UNIV_INLINE 466 ulint dict_index_is_sec_or_ibuf(const dict_index_t *index) /*!< in: index */ 467 MY_ATTRIBUTE((warn_unused_result)); 468 469 /** Get all the FTS indexes on a table. 470 @param[in] table table 471 @param[out] indexes all FTS indexes on this table 472 @return number of FTS indexes */ 473 ulint dict_table_get_all_fts_indexes(dict_table_t *table, ib_vector_t *indexes); 474 475 UNIV_INLINE 476 ulint dict_table_get_n_tot_u_cols(const dict_table_t *table); 477 478 /** Gets the number of virtual columns in a table in the dictionary cache. 479 @param[in] table the table to check 480 @return number of virtual columns of a table */ 481 UNIV_INLINE 482 ulint dict_table_get_n_v_cols(const dict_table_t *table); 483 484 /** Check if a table has indexed virtual columns 485 @param[in] table the table to check 486 @return true is the table has indexed virtual columns */ 487 UNIV_INLINE 488 bool dict_table_has_indexed_v_cols(const dict_table_t *table); 489 490 /** Gets the approximately estimated number of rows in the table. 491 @return estimated number of rows */ 492 UNIV_INLINE 493 ib_uint64_t dict_table_get_n_rows(const dict_table_t *table) /*!< in: table */ 494 MY_ATTRIBUTE((warn_unused_result)); 495 /** Increment the number of rows in the table by one. 496 Notice that this operation is not protected by any latch, the number is 497 approximate. */ 498 UNIV_INLINE 499 void dict_table_n_rows_inc(dict_table_t *table); /*!< in/out: table */ 500 /** Decrement the number of rows in the table by one. 501 Notice that this operation is not protected by any latch, the number is 502 approximate. */ 503 UNIV_INLINE 504 void dict_table_n_rows_dec(dict_table_t *table); /*!< in/out: table */ 505 506 /** Get nth virtual column 507 @param[in] table target table 508 @param[in] col_nr column number in MySQL Table definition 509 @return dict_v_col_t ptr */ 510 dict_v_col_t *dict_table_get_nth_v_col_mysql(const dict_table_t *table, 511 ulint col_nr); 512 513 #ifdef UNIV_DEBUG 514 /** Gets the nth virtual column of a table. 515 @param[in] table table 516 @param[in] pos position of virtual column 517 @return pointer to virtual column object */ 518 UNIV_INLINE 519 dict_v_col_t *dict_table_get_nth_v_col(const dict_table_t *table, ulint pos); 520 521 #else /* UNIV_DEBUG */ 522 /* Get nth virtual columns */ 523 #define dict_table_get_nth_v_col(table, pos) ((table)->v_cols + (pos)) 524 #endif /* UNIV_DEBUG */ 525 /** Gets the given system column number of a table. 526 @return column number */ 527 UNIV_INLINE 528 ulint dict_table_get_sys_col_no(const dict_table_t *table, /*!< in: table */ 529 ulint sys) /*!< in: DATA_ROW_ID, ... */ 530 MY_ATTRIBUTE((warn_unused_result)); 531 /** Check whether the table uses the compact page format. 532 @return true if table uses the compact page format */ 533 UNIV_INLINE 534 ibool dict_table_is_comp(const dict_table_t *table) /*!< in: table */ 535 MY_ATTRIBUTE((warn_unused_result)); 536 537 /** Determine if a table uses atomic BLOBs (no locally stored prefix). 538 @param[in] table InnoDB table 539 @return whether BLOBs are atomic */ 540 UNIV_INLINE 541 bool dict_table_has_atomic_blobs(const dict_table_t *table) 542 MY_ATTRIBUTE((warn_unused_result)); 543 544 #ifndef UNIV_HOTBACKUP 545 /** Set the various values in a dict_table_t::flags pointer. 546 @param[in,out] flags Pointer to a 4 byte Table Flags 547 @param[in] format File Format 548 @param[in] zip_ssize Zip Shift Size 549 @param[in] use_data_dir Table uses DATA DIRECTORY 550 @param[in] shared_space Table uses a General Shared Tablespace */ 551 UNIV_INLINE 552 void dict_tf_set(uint32_t *flags, rec_format_t format, uint32_t zip_ssize, 553 bool use_data_dir, bool shared_space); 554 555 /** Initialize a dict_table_t::flags pointer. 556 @param[in] compact Table uses Compact or greater 557 @param[in] zip_ssize Zip Shift Size (log 2 minus 9) 558 @param[in] atomic_blobs Table uses Compressed or Dynamic 559 @param[in] data_dir Table uses DATA DIRECTORY 560 @param[in] shared_space Table uses a General Shared Tablespace */ 561 UNIV_INLINE 562 uint32_t dict_tf_init(bool compact, ulint zip_ssize, bool atomic_blobs, 563 bool data_dir, bool shared_space); 564 565 /** Convert a 32 bit integer table flags to the 32 bit FSP Flags. 566 Fsp Flags are written into the tablespace header at the offset 567 FSP_SPACE_FLAGS and are also stored in the fil_space_t::flags field. 568 The following chart shows the translation of the low order bit. 569 Other bits are the same. 570 ========================= Low order bit ========================== 571 | REDUNDANT | COMPACT | COMPRESSED | DYNAMIC 572 dict_table_t::flags | 0 | 1 | 1 | 1 573 fil_space_t::flags | 0 | 0 | 1 | 1 574 ================================================================== 575 @param[in] table_flags dict_table_t::flags 576 @return tablespace flags (fil_space_t::flags) */ 577 uint32_t dict_tf_to_fsp_flags(uint32_t table_flags); 578 579 /** Extract the page size from table flags. 580 @param[in] flags flags 581 @return compressed page size, or 0 if not compressed */ 582 UNIV_INLINE 583 const page_size_t dict_tf_get_page_size(uint32_t flags); 584 #endif /* !UNIV_HOTBACKUP */ 585 586 /** Determine the extent size (in pages) for the given table 587 @param[in] table the table whose extent size is being 588 calculated. 589 @return extent size in pages (256, 128 or 64) */ 590 page_no_t dict_table_extent_size(const dict_table_t *table); 591 592 /** Get the table page size. 593 @param[in] table table 594 @return compressed page size, or 0 if not compressed */ 595 UNIV_INLINE 596 const page_size_t dict_table_page_size(const dict_table_t *table) 597 MY_ATTRIBUTE((warn_unused_result)); 598 599 #ifndef UNIV_HOTBACKUP 600 /** Obtain exclusive locks on all index trees of the table. This is to prevent 601 accessing index trees while InnoDB is updating internal metadata for 602 operations such as FLUSH TABLES. */ 603 UNIV_INLINE 604 void dict_table_x_lock_indexes(dict_table_t *table); /*!< in: table */ 605 /** Release the exclusive locks on all index tree. */ 606 UNIV_INLINE 607 void dict_table_x_unlock_indexes(dict_table_t *table); /*!< in: table */ 608 #endif /* !UNIV_HOTBACKUP */ 609 /** Checks if a column is in the ordering columns of the clustered index of a 610 table. Column prefixes are treated like whole columns. 611 @return true if the column, or its prefix, is in the clustered key */ 612 ibool dict_table_col_in_clustered_key( 613 const dict_table_t *table, /*!< in: table */ 614 ulint n) /*!< in: column number */ 615 MY_ATTRIBUTE((warn_unused_result)); 616 /** Check if the table has an FTS index. 617 @return true if table has an FTS index */ 618 UNIV_INLINE 619 ibool dict_table_has_fts_index(dict_table_t *table) /*!< in: table */ 620 MY_ATTRIBUTE((warn_unused_result)); 621 /** Copies types of virtual columns contained in table to tuple and sets all 622 fields of the tuple to the SQL NULL value. This function should 623 be called right after dtuple_create(). 624 @param[in,out] tuple data tuple 625 @param[in] table table */ 626 void dict_table_copy_v_types(dtuple_t *tuple, const dict_table_t *table); 627 /** Copies types of columns contained in table to tuple and sets all 628 fields of the tuple to the SQL NULL value. This function should 629 be called right after dtuple_create(). */ 630 void dict_table_copy_types(dtuple_t *tuple, /*!< in/out: data tuple */ 631 const dict_table_t *table); /*!< in: table */ 632 #ifndef UNIV_HOTBACKUP 633 /******************************************************************** 634 Wait until all the background threads of the given table have exited, i.e., 635 bg_threads == 0. Note: bg_threads_mutex must be reserved when 636 calling this. */ 637 void dict_table_wait_for_bg_threads_to_exit( 638 dict_table_t *table, /* in: table */ 639 ulint delay); /* in: time in microseconds to wait between 640 checks of bg_threads. */ 641 /** Look up an index. 642 @param[in] id index identifier 643 @return index or NULL if not found */ 644 const dict_index_t *dict_index_find(const index_id_t &id) 645 MY_ATTRIBUTE((warn_unused_result)); 646 /** Make room in the table cache by evicting an unused table. The unused table 647 should not be part of FK relationship and currently not used in any user 648 transaction. There is no guarantee that it will remove a table. 649 @return number of tables evicted. */ 650 ulint dict_make_room_in_cache( 651 ulint max_tables, /*!< in: max tables allowed in cache */ 652 ulint pct_check); /*!< in: max percent to check */ 653 654 #define BIG_ROW_SIZE 1024 655 656 /** Adds an index to the dictionary cache. 657 @param[in] table table on which the index is 658 @param[in] index index; NOTE! The index memory 659 object is freed in this function! 660 @param[in] page_no root page number of the index 661 @param[in] strict TRUE=refuse to create the index 662 if records could be too big to fit in 663 an B-tree page 664 @return DB_SUCCESS, DB_TOO_BIG_RECORD, or DB_CORRUPTION */ 665 dberr_t dict_index_add_to_cache( 666 dict_table_t *table, /*!< in: table on which the index is */ 667 dict_index_t *index, /*!< in, own: index; NOTE! The index memory 668 object is freed in this function! */ 669 page_no_t page_no, /*!< in: root page number of the index */ 670 ibool strict) /*!< in: TRUE=refuse to create the index 671 if records could be too big to fit in 672 an B-tree page */ 673 MY_ATTRIBUTE((warn_unused_result)); 674 675 /** Clears the virtual column's index list before index is being freed. 676 @param[in] index Index being freed */ 677 void dict_index_remove_from_v_col_list(dict_index_t *index); 678 679 /** Adds an index to the dictionary cache, with possible indexing newly 680 added column. 681 @param[in] table table on which the index is 682 @param[in] index index; NOTE! The index memory 683 object is freed in this function! 684 @param[in] add_v new virtual column that being added along with 685 an add index call 686 @param[in] page_no root page number of the index 687 @param[in] strict TRUE=refuse to create the index 688 if records could be too big to fit in 689 an B-tree page 690 @return DB_SUCCESS, DB_TOO_BIG_RECORD, or DB_CORRUPTION */ 691 dberr_t dict_index_add_to_cache_w_vcol(dict_table_t *table, dict_index_t *index, 692 const dict_add_v_col_t *add_v, 693 page_no_t page_no, ibool strict) 694 MY_ATTRIBUTE((warn_unused_result)); 695 #endif /* !UNIV_HOTBACKUP */ 696 /** Gets the number of fields in the internal representation of an index, 697 including fields added by the dictionary system. 698 @return number of fields */ 699 UNIV_INLINE 700 ulint dict_index_get_n_fields( 701 const dict_index_t *index) /*!< in: an internal 702 representation of index (in 703 the dictionary cache) */ 704 MY_ATTRIBUTE((warn_unused_result)); 705 /** Gets the number of fields in the internal representation of an index 706 that uniquely determine the position of an index entry in the index, if 707 we do not take multiversioning into account: in the B-tree use the value 708 returned by dict_index_get_n_unique_in_tree. 709 @return number of fields */ 710 UNIV_INLINE 711 ulint dict_index_get_n_unique( 712 const dict_index_t *index) /*!< in: an internal representation 713 of index (in the dictionary cache) */ 714 MY_ATTRIBUTE((warn_unused_result)); 715 /** Gets the number of fields in the internal representation of an index 716 which uniquely determine the position of an index entry in the index, if 717 we also take multiversioning into account. 718 @return number of fields */ 719 UNIV_INLINE 720 ulint dict_index_get_n_unique_in_tree( 721 const dict_index_t *index) /*!< in: an internal representation 722 of index (in the dictionary cache) */ 723 MY_ATTRIBUTE((warn_unused_result)); 724 725 /** The number of fields in the nonleaf page of spatial index, except 726 the page no field. */ 727 #define DICT_INDEX_SPATIAL_NODEPTR_SIZE 1 728 /** 729 Gets the number of fields on nonleaf page level in the internal representation 730 of an index which uniquely determine the position of an index entry in the 731 index, if we also take multiversioning into account. Note, it doesn't 732 include page no field. 733 @param[in] index index 734 @return number of fields */ 735 UNIV_INLINE 736 uint16_t dict_index_get_n_unique_in_tree_nonleaf(const dict_index_t *index) 737 MY_ATTRIBUTE((warn_unused_result)); 738 /** Gets the number of user-defined ordering fields in the index. In the 739 internal representation we add the row id to the ordering fields to make all 740 indexes unique, but this function returns the number of fields the user defined 741 in the index as ordering fields. 742 @return number of fields */ 743 UNIV_INLINE 744 ulint dict_index_get_n_ordering_defined_by_user( 745 const dict_index_t *index) /*!< in: an internal representation 746 of index (in the dictionary cache) */ 747 MY_ATTRIBUTE((warn_unused_result)); 748 /** Returns TRUE if the index contains a column or a prefix of that column. 749 @return true if contains the column or its prefix */ 750 ibool dict_index_contains_col_or_prefix( 751 const dict_index_t *index, /*!< in: index */ 752 ulint n, /*!< in: column number */ 753 bool is_virtual) 754 /*!< in: whether it is a virtual col */ 755 MY_ATTRIBUTE((warn_unused_result)); 756 /** Looks for a matching field in an index. The column has to be the same. The 757 column in index must be complete, or must contain a prefix longer than the 758 column in index2. That is, we must be able to construct the prefix in index2 759 from the prefix in index. 760 @return position in internal representation of the index; 761 ULINT_UNDEFINED if not contained */ 762 ulint dict_index_get_nth_field_pos( 763 const dict_index_t *index, /*!< in: index from which to search */ 764 const dict_index_t *index2, /*!< in: index */ 765 ulint n) /*!< in: field number in index2 */ 766 MY_ATTRIBUTE((warn_unused_result)); 767 /** Looks for non-virtual column n position in the clustered index. 768 @return position in internal representation of the clustered index */ 769 ulint dict_table_get_nth_col_pos(const dict_table_t *table, /*!< in: table */ 770 ulint n) /*!< in: column number */ 771 MY_ATTRIBUTE((warn_unused_result)); 772 773 /** Get the innodb column position for a non-virtual column according to 774 its original MySQL table position n 775 @param[in] table table 776 @param[in] n MySQL column position 777 @return column position in InnoDB */ 778 ulint dict_table_mysql_pos_to_innodb(const dict_table_t *table, ulint n); 779 780 /** Copies types of fields contained in index to tuple. */ 781 void dict_index_copy_types(dtuple_t *tuple, /*!< in/out: data tuple */ 782 const dict_index_t *index, /*!< in: index */ 783 ulint n_fields); /*!< in: number of 784 field types to copy */ 785 #ifdef UNIV_DEBUG 786 /** Checks that a tuple has n_fields_cmp value in a sensible range, so that 787 no comparison can occur with the page number field in a node pointer. 788 @return true if ok */ 789 ibool dict_index_check_search_tuple( 790 const dict_index_t *index, /*!< in: index tree */ 791 const dtuple_t *tuple) /*!< in: tuple used in a search */ 792 MY_ATTRIBUTE((warn_unused_result)); 793 /** Whether and when to allow temporary index names */ 794 enum check_name { 795 /** Require all indexes to be complete. */ 796 CHECK_ALL_COMPLETE, 797 /** Allow aborted online index creation. */ 798 CHECK_ABORTED_OK, 799 /** Allow partial indexes to exist. */ 800 CHECK_PARTIAL_OK 801 }; 802 /** Check for duplicate index entries in a table [using the index name] */ 803 void dict_table_check_for_dup_indexes( 804 const dict_table_t *table, /*!< in: Check for dup indexes 805 in this table */ 806 enum check_name check); /*!< in: whether and when to allow 807 temporary index names */ 808 /** Check if a table is a temporary table with compressed row format, 809 we should always expect false. 810 @param[in] table table 811 @return true if it's a compressed temporary table, false otherwise */ 812 inline bool dict_table_is_compressed_temporary(const dict_table_t *table); 813 #endif /* UNIV_DEBUG */ 814 /** Builds a node pointer out of a physical record and a page number. 815 @return own: node pointer */ 816 dtuple_t *dict_index_build_node_ptr(const dict_index_t *index, /*!< in: index */ 817 const rec_t *rec, /*!< in: record for which 818 to build node pointer */ 819 page_no_t page_no, /*!< in: page number to 820 put in node pointer */ 821 mem_heap_t *heap, /*!< in: memory heap where 822 pointer created */ 823 ulint level) /*!< in: level of rec in tree: 824 0 means leaf level */ 825 MY_ATTRIBUTE((warn_unused_result)); 826 /** Copies an initial segment of a physical record, long enough to specify an 827 index entry uniquely. 828 @return pointer to the prefix record */ 829 rec_t *dict_index_copy_rec_order_prefix( 830 const dict_index_t *index, /*!< in: index */ 831 const rec_t *rec, /*!< in: record for which to 832 copy prefix */ 833 ulint *n_fields, /*!< out: number of fields copied */ 834 byte **buf, /*!< in/out: memory buffer for the 835 copied prefix, or NULL */ 836 size_t *buf_size) /*!< in/out: buffer size */ 837 MY_ATTRIBUTE((warn_unused_result)); 838 /** Builds a typed data tuple out of a physical record. 839 @return own: data tuple */ 840 dtuple_t *dict_index_build_data_tuple( 841 dict_index_t *index, /*!< in: index */ 842 rec_t *rec, /*!< in: record for which to build data tuple */ 843 ulint n_fields, /*!< in: number of data fields */ 844 mem_heap_t *heap) /*!< in: memory heap where tuple created */ 845 MY_ATTRIBUTE((warn_unused_result)); 846 /** Gets the space id of the root of the index tree. 847 @return space id */ 848 UNIV_INLINE 849 space_id_t dict_index_get_space(const dict_index_t *index) /*!< in: index */ 850 MY_ATTRIBUTE((warn_unused_result)); 851 852 /** Sets the space id of the root of the index tree. 853 @param[in,out] index index 854 @param[in] space space id */ 855 UNIV_INLINE 856 void dict_index_set_space(dict_index_t *index, space_id_t space); 857 858 /** Gets the page number of the root of the index tree. 859 @return page number */ 860 UNIV_INLINE 861 page_no_t dict_index_get_page(const dict_index_t *tree) /*!< in: index */ 862 MY_ATTRIBUTE((warn_unused_result)); 863 /** Gets the read-write lock of the index tree. 864 @return read-write lock */ 865 UNIV_INLINE 866 rw_lock_t *dict_index_get_lock(dict_index_t *index) /*!< in: index */ 867 MY_ATTRIBUTE((warn_unused_result)); 868 /** Returns free space reserved for future updates of records. This is 869 relevant only in the case of many consecutive inserts, as updates 870 which make the records bigger might fragment the index. 871 @return number of free bytes on page, reserved for updates */ 872 UNIV_INLINE 873 ulint dict_index_get_space_reserve(void); 874 875 /* Online index creation @{ */ 876 /** Gets the status of online index creation. 877 @return the status */ 878 UNIV_INLINE 879 enum online_index_status dict_index_get_online_status( 880 const dict_index_t *index) /*!< in: secondary index */ 881 MY_ATTRIBUTE((warn_unused_result)); 882 883 /** Sets the status of online index creation. 884 @param[in,out] index index 885 @param[in] status status */ 886 UNIV_INLINE 887 void dict_index_set_online_status(dict_index_t *index, 888 enum online_index_status status); 889 890 /** Determines if a secondary index is being or has been created online, 891 or if the table is being rebuilt online, allowing concurrent modifications 892 to the table. 893 @retval true if the index is being or has been built online, or 894 if this is a clustered index and the table is being or has been rebuilt online 895 @retval false if the index has been created or the table has been 896 rebuilt completely */ 897 UNIV_INLINE 898 bool dict_index_is_online_ddl(const dict_index_t *index) /*!< in: index */ 899 MY_ATTRIBUTE((warn_unused_result)); 900 /** Calculates the minimum record length in an index. */ 901 ulint dict_index_calc_min_rec_len(const dict_index_t *index) /*!< in: index */ 902 MY_ATTRIBUTE((warn_unused_result)); 903 /** Reserves the dictionary system mutex for MySQL. */ 904 void dict_mutex_enter_for_mysql(void); 905 /** Releases the dictionary system mutex for MySQL. */ 906 void dict_mutex_exit_for_mysql(void); 907 908 #ifndef UNIV_HOTBACKUP 909 /** Create a dict_table_t's stats latch or delay for lazy creation. 910 This function is only called from either single threaded environment 911 or from a thread that has not shared the table object with other threads. 912 @param[in,out] table table whose stats latch to create 913 @param[in] enabled if false then the latch is disabled 914 and dict_table_stats_lock()/unlock() become noop on this table. */ 915 void dict_table_stats_latch_create(dict_table_t *table, bool enabled); 916 917 /** Destroy a dict_table_t's stats latch. 918 This function is only called from either single threaded environment 919 or from a thread that has not shared the table object with other threads. 920 @param[in,out] table table whose stats latch to destroy */ 921 void dict_table_stats_latch_destroy(dict_table_t *table); 922 923 /** Lock the appropriate latch to protect a given table's statistics. 924 @param[in] table table whose stats to lock 925 @param[in] latch_mode RW_S_LATCH or RW_X_LATCH */ 926 void dict_table_stats_lock(dict_table_t *table, ulint latch_mode); 927 928 /** Unlock the latch that has been locked by dict_table_stats_lock(). 929 @param[in] table table whose stats to unlock 930 @param[in] latch_mode RW_S_LATCH or RW_X_LATCH */ 931 void dict_table_stats_unlock(dict_table_t *table, ulint latch_mode); 932 933 /** Checks if the database name in two table names is the same. 934 @return true if same db name */ 935 ibool dict_tables_have_same_db(const char *name1, /*!< in: table name in the 936 form dbname '/' tablename */ 937 const char *name2) /*!< in: table name in the 938 form dbname '/' tablename */ 939 MY_ATTRIBUTE((warn_unused_result)); 940 /** Get an index by name. 941 @param[in] table the table where to look for the index 942 @param[in] name the index name to look for 943 @param[in] committed true=search for committed, 944 false=search for uncommitted 945 @return index, NULL if does not exist */ 946 dict_index_t *dict_table_get_index_on_name(dict_table_t *table, 947 const char *name, 948 bool committed = true) 949 MY_ATTRIBUTE((warn_unused_result)); 950 /** Get an index by name. 951 @param[in] table the table where to look for the index 952 @param[in] name the index name to look for 953 @param[in] committed true=search for committed, 954 false=search for uncommitted 955 @return index, NULL if does not exist */ 956 inline const dict_index_t *dict_table_get_index_on_name( 957 const dict_table_t *table, const char *name, bool committed = true) { 958 return (dict_table_get_index_on_name(const_cast<dict_table_t *>(table), name, 959 committed)); 960 } 961 962 /*************************************************************** 963 Check whether a column exists in an FTS index. */ 964 UNIV_INLINE 965 ulint dict_table_is_fts_column( 966 /*!< out: ULINT_UNDEFINED if no match else 967 the offset within the vector */ 968 ib_vector_t *indexes, /*!< in: vector containing only FTS indexes */ 969 ulint col_no, /*!< in: col number to search for */ 970 bool is_virtual) /*!< in: whether it is a virtual column */ 971 MY_ATTRIBUTE((warn_unused_result)); 972 /** Prevent table eviction by moving a table to the non-LRU list from the 973 LRU list if it is not already there. */ 974 UNIV_INLINE 975 void dict_table_prevent_eviction( 976 dict_table_t *table); /*!< in: table to prevent eviction */ 977 978 /** Allow the table to be evicted by moving a table to the LRU list from 979 the non-LRU list if it is not already there. 980 @param[in] table InnoDB table object can be evicted */ 981 UNIV_INLINE 982 void dict_table_allow_eviction(dict_table_t *table); 983 984 /** Move this table to non-LRU list for DDL operations if it's 985 currently not there. This also prevents later opening table via DD objects, 986 when the table name in InnoDB doesn't match with DD object. 987 @param[in,out] table Table to put in non-LRU list */ 988 UNIV_INLINE 989 void dict_table_ddl_acquire(dict_table_t *table); 990 991 /** Move this table to LRU list after DDL operations if it was moved 992 to non-LRU list 993 @param[in,out] table Table to put in LRU list */ 994 UNIV_INLINE 995 void dict_table_ddl_release(dict_table_t *table); 996 997 /** Move a table to the non LRU end of the LRU list. */ 998 void dict_table_move_from_lru_to_non_lru( 999 dict_table_t *table); /*!< in: table to move from LRU to non-LRU */ 1000 1001 /** Move a table to the LRU end from the non LRU list. 1002 @param[in] table InnoDB table object */ 1003 void dict_table_move_from_non_lru_to_lru(dict_table_t *table); 1004 1005 /** Move to the most recently used segment of the LRU list. */ 1006 void dict_move_to_mru(dict_table_t *table); /*!< in: table to move to MRU */ 1007 1008 /** Maximum number of columns in a foreign key constraint. Please Note MySQL 1009 has a much lower limit on the number of columns allowed in a foreign key 1010 constraint */ 1011 #define MAX_NUM_FK_COLUMNS 500 1012 1013 /* Buffers for storing detailed information about the latest foreign key 1014 and unique key errors */ 1015 extern FILE *dict_foreign_err_file; 1016 extern ib_mutex_t dict_foreign_err_mutex; /* mutex protecting the 1017 foreign key error messages */ 1018 #endif /* !UNIV_HOTBACKUP */ 1019 1020 /** the dictionary system */ 1021 extern dict_sys_t *dict_sys; 1022 #ifndef UNIV_HOTBACKUP 1023 /** the data dictionary rw-latch protecting dict_sys */ 1024 extern rw_lock_t *dict_operation_lock; 1025 1026 /** Forward declaration */ 1027 class DDTableBuffer; 1028 #endif /* !UNIV_HOTBACKUP */ 1029 struct dict_persist_t; 1030 1031 /** the dictionary persisting structure */ 1032 extern dict_persist_t *dict_persist; 1033 1034 /* Dictionary system struct */ 1035 struct dict_sys_t { 1036 #ifndef UNIV_HOTBACKUP 1037 DictSysMutex mutex; /*!< mutex protecting the data 1038 dictionary; protects also the 1039 disk-based dictionary system tables; 1040 this mutex serializes CREATE TABLE 1041 and DROP TABLE, as well as reading 1042 the dictionary data for a table from 1043 system tables */ 1044 #endif /* !UNIV_HOTBACKUP */ 1045 row_id_t row_id; /*!< the next row id to assign; 1046 NOTE that at a checkpoint this 1047 must be written to the dict system 1048 header and flushed to a file; in 1049 recovery this must be derived from 1050 the log records */ 1051 hash_table_t *table_hash; /*!< hash table of the tables, based 1052 on name */ 1053 hash_table_t *table_id_hash; /*!< hash table of the tables, based 1054 on id */ 1055 lint size; /*!< varying space in bytes occupied 1056 by the data dictionary table and 1057 index objects */ 1058 /** Handler to sys_* tables, they're only for upgrade */ 1059 dict_table_t *sys_tables; /*!< SYS_TABLES table */ 1060 dict_table_t *sys_columns; /*!< SYS_COLUMNS table */ 1061 dict_table_t *sys_indexes; /*!< SYS_INDEXES table */ 1062 dict_table_t *sys_fields; /*!< SYS_FIELDS table */ 1063 dict_table_t *sys_virtual; /*!< SYS_VIRTUAL table */ 1064 1065 /** Permanent handle to mysql.innodb_table_stats */ 1066 dict_table_t *table_stats; 1067 /** Permanent handle to mysql.innodb_index_stats */ 1068 dict_table_t *index_stats; 1069 /** Permanent handle to mysql.innodb_ddl_log */ 1070 dict_table_t *ddl_log; 1071 /** Permanent handle to mysql.innodb_dynamic_metadata */ 1072 dict_table_t *dynamic_metadata; 1073 1074 UT_LIST_BASE_NODE_T(dict_table_t) 1075 table_LRU; /*!< List of tables that can be evicted 1076 from the cache */ 1077 UT_LIST_BASE_NODE_T(dict_table_t) 1078 table_non_LRU; /*!< List of tables that can't be 1079 evicted from the cache */ 1080 1081 /** Iterate each table. 1082 @tparam Functor visitor 1083 @param[in,out] functor to be invoked on each table */ 1084 template <typename Functor> for_each_tabledict_sys_t1085 void for_each_table(Functor &functor) { 1086 mutex_enter(&mutex); 1087 1088 hash_table_t *hash = table_id_hash; 1089 1090 for (ulint i = 0; i < hash->n_cells; i++) { 1091 for (dict_table_t *table = 1092 static_cast<dict_table_t *>(HASH_GET_FIRST(hash, i)); 1093 table; 1094 table = static_cast<dict_table_t *>(HASH_GET_NEXT(id_hash, table))) { 1095 functor(table); 1096 } 1097 } 1098 1099 mutex_exit(&mutex); 1100 } 1101 1102 /** Check if a tablespace id is a reserved one 1103 @param[in] space tablespace id to check 1104 @return true if a reserved tablespace id, otherwise false */ is_reserveddict_sys_t1105 static bool is_reserved(space_id_t space) { 1106 return (space >= dict_sys_t::s_reserved_space_id || 1107 fsp_is_session_temporary(space)); 1108 } 1109 1110 /** Set of ids of DD tables */ 1111 static std::set<dd::Object_id> s_dd_table_ids; 1112 1113 /** Check if a table is hardcoded. it only includes the dd tables 1114 @param[in] id table ID 1115 @retval true if the table is a persistent hard-coded table 1116 (dict_table_t::is_temporary() will not hold) 1117 @retval false if the table is not hard-coded 1118 (it can be persistent or temporary) */ is_dd_table_iddict_sys_t1119 static bool is_dd_table_id(table_id_t id) { 1120 return (s_dd_table_ids.find(id) != s_dd_table_ids.end()); 1121 } 1122 1123 /** The first ID of the redo log pseudo-tablespace */ 1124 static constexpr space_id_t s_log_space_first_id = 0xFFFFFFF0UL; 1125 1126 /** Use maximum UINT value to indicate invalid space ID. */ 1127 static constexpr space_id_t s_invalid_space_id = 0xFFFFFFFF; 1128 1129 /** The data dictionary tablespace ID. */ 1130 static constexpr space_id_t s_space_id = 0xFFFFFFFE; 1131 1132 /** The innodb_temporary tablespace ID. */ 1133 static constexpr space_id_t s_temp_space_id = 0xFFFFFFFD; 1134 1135 /** The number of space IDs dedicated to each undo tablespace */ 1136 static constexpr space_id_t undo_space_id_range = 512; 1137 1138 /** The lowest undo tablespace ID. */ 1139 static constexpr space_id_t s_min_undo_space_id = 1140 s_log_space_first_id - (FSP_MAX_UNDO_TABLESPACES * undo_space_id_range); 1141 1142 /** The highest undo tablespace ID. */ 1143 static constexpr space_id_t s_max_undo_space_id = s_log_space_first_id - 1; 1144 1145 /** The first reserved tablespace ID */ 1146 static constexpr space_id_t s_reserved_space_id = s_min_undo_space_id; 1147 1148 /** Leave 1K space_ids and start space_ids for temporary 1149 general tablespaces (total 400K space_ids)*/ 1150 static constexpr space_id_t s_max_temp_space_id = s_reserved_space_id - 1000; 1151 1152 /** Lowest temporary general space id */ 1153 static constexpr space_id_t s_min_temp_space_id = 1154 s_reserved_space_id - 1000 - 400000; 1155 1156 /** The dd::Tablespace::id of the dictionary tablespace. */ 1157 static constexpr dd::Object_id s_dd_space_id = 1; 1158 1159 /** The dd::Tablespace::id of innodb_system. */ 1160 static constexpr dd::Object_id s_dd_sys_space_id = 2; 1161 1162 /** The dd::Tablespace::id of innodb_temporary. */ 1163 static constexpr dd::Object_id s_dd_temp_space_id = 3; 1164 1165 /** The name of the data dictionary tablespace. */ 1166 static const char *s_dd_space_name; 1167 1168 /** The file name of the data dictionary tablespace. */ 1169 static const char *s_dd_space_file_name; 1170 1171 /** The name of the hard-coded system tablespace. */ 1172 static const char *s_sys_space_name; 1173 1174 /** The name of the predefined temporary tablespace. */ 1175 static const char *s_temp_space_name; 1176 1177 /** The file name of the predefined temporary tablespace. */ 1178 static const char *s_temp_space_file_name; 1179 1180 /** The hard-coded tablespace name innodb_file_per_table. */ 1181 static const char *s_file_per_table_name; 1182 1183 /** These two undo tablespaces cannot be dropped. */ 1184 static const char *s_default_undo_space_name_1; 1185 static const char *s_default_undo_space_name_2; 1186 1187 /** The table ID of mysql.innodb_dynamic_metadata */ 1188 static constexpr table_id_t s_dynamic_meta_table_id = 2; 1189 1190 /** The clustered index ID of mysql.innodb_dynamic_metadata */ 1191 static constexpr space_index_t s_dynamic_meta_index_id = 2; 1192 }; 1193 1194 /** Structure for persisting dynamic metadata of data dictionary */ 1195 struct dict_persist_t { 1196 /** Mutex to protect data in this structure, also the 1197 dict_table_t::dirty_status and 1198 dict_table_t::in_dirty_dict_tables_list 1199 This mutex should be low-level one so that it can be used widely 1200 when necessary, so its level had to be above SYNC_LOG. However, 1201 after this mutex, persister may have to access B-tree and require 1202 tree latch, the latch level of this mutex then has to be right 1203 before the SYNC_INDEX_TREE. */ 1204 ib_mutex_t mutex; 1205 1206 /** List of tables whose dirty_status are marked as METADATA_DIRTY, 1207 or METADATA_BUFFERED. It's protected by the mutex */ 1208 UT_LIST_BASE_NODE_T(dict_table_t) 1209 dirty_dict_tables; 1210 1211 /** Number of the tables which are of status METADATA_DIRTY. 1212 It's protected by the mutex */ 1213 std::atomic<uint32_t> num_dirty_tables; 1214 1215 #ifndef UNIV_HOTBACKUP 1216 /** DDTableBuffer table for persistent dynamic metadata */ 1217 DDTableBuffer *table_buffer; 1218 #endif /* !UNIV_HOTBACKUP */ 1219 1220 /** Collection of instances to persist dynamic metadata */ 1221 Persisters *persisters; 1222 }; 1223 1224 #ifndef UNIV_HOTBACKUP 1225 /** dummy index for ROW_FORMAT=REDUNDANT supremum and infimum records */ 1226 extern dict_index_t *dict_ind_redundant; 1227 1228 /** Inits dict_ind_redundant. */ 1229 void dict_ind_init(void); 1230 1231 /** Converts a database and table name from filesystem encoding (e.g. 1232 "@code d@i1b/a@q1b@1Kc @endcode", same format as used in dict_table_t::name) 1233 in two strings in UTF8 encoding (e.g. dцb and aюbØc). The output buffers must 1234 be at least MAX_DB_UTF8_LEN and MAX_TABLE_UTF8_LEN bytes. 1235 @param[in] db_and_table database and table names, 1236 e.g. "@code d@i1b/a@q1b@1Kc @endcode" 1237 @param[out] db_utf8 database name, e.g. dцb 1238 @param[in] db_utf8_size dbname_utf8 size 1239 @param[out] table_utf8 table name, e.g. aюbØc 1240 @param[in] table_utf8_size table_utf8 size */ 1241 void dict_fs2utf8(const char *db_and_table, char *db_utf8, size_t db_utf8_size, 1242 char *table_utf8, size_t table_utf8_size); 1243 1244 /** Resize the hash tables besed on the current buffer pool size. */ 1245 void dict_resize(); 1246 1247 /** Wrapper for the mysql.innodb_dynamic_metadata used to buffer the persistent 1248 dynamic metadata. 1249 This should be a table with only clustered index, no delete-marked records, 1250 no locking, no undo logging, no purge, no adaptive hash index. 1251 We should always use low level btr functions to access and modify the table. 1252 Accessing this table should be protected by dict_sys->mutex */ 1253 class DDTableBuffer { 1254 public: 1255 /** Default constructor */ 1256 DDTableBuffer(); 1257 1258 /** Destructor */ 1259 ~DDTableBuffer(); 1260 1261 /** Replace the dynamic metadata for a specific table 1262 @param[in] id table id 1263 @param[in] version table dynamic metadata version 1264 @param[in] metadata the metadata we want to replace 1265 @param[in] len the metadata length 1266 @return DB_SUCCESS or error code */ 1267 dberr_t replace(table_id_t id, uint64_t version, const byte *metadata, 1268 size_t len); 1269 1270 /** Remove the whole row for a specific table 1271 @param[in] id table id 1272 @return DB_SUCCESS or error code */ 1273 dberr_t remove(table_id_t id); 1274 1275 /** Truncate the table. We can call it after all the dynamic 1276 metadata has been written back to DD table */ 1277 void truncate(void); 1278 1279 /** Get the buffered metadata for a specific table, the caller 1280 has to delete the returned std::string object by UT_DELETE 1281 @param[in] id table id 1282 @param[out] version table dynamic metadata version 1283 @return the metadata saved in a string object, if nothing, the 1284 string would be of length 0 */ 1285 std::string *get(table_id_t id, uint64 *version); 1286 1287 private: 1288 /** Initialize m_index, the in-memory clustered index of the table 1289 and two tuples used in this class */ 1290 void init(); 1291 1292 /** Open the mysql.innodb_dynamic_metadata when DD is not fully up */ 1293 void open(); 1294 1295 /** Create the search and replace tuples */ 1296 void create_tuples(); 1297 1298 /** Initialize the id field of tuple 1299 @param[out] tuple the tuple to be initialized 1300 @param[in] id table id */ 1301 void init_tuple_with_id(dtuple_t *tuple, table_id_t id); 1302 1303 /** Free the things initialized in init() */ 1304 void close(); 1305 1306 /** Prepare for a update on METADATA field 1307 @param[in] entry clustered index entry to replace rec 1308 @param[in] rec clustered index record 1309 @return update vector of differing fields without system columns, 1310 or NULL if there isn't any different field */ 1311 upd_t *update_set_metadata(const dtuple_t *entry, const rec_t *rec); 1312 1313 private: 1314 /** The clustered index of this system table */ 1315 dict_index_t *m_index; 1316 1317 /** The heap used for dynamic allocations, which should always 1318 be freed before return */ 1319 mem_heap_t *m_dynamic_heap; 1320 1321 /** The heap used during replace() operation, which should always 1322 be freed before return */ 1323 mem_heap_t *m_replace_heap; 1324 1325 /** The heap used to create the search tuple and replace tuple */ 1326 mem_heap_t *m_heap; 1327 1328 /** The tuple used to search for specified table, it's protected 1329 by dict_persist->mutex */ 1330 dtuple_t *m_search_tuple; 1331 1332 /** The tuple used to replace for specified table, it's protected 1333 by dict_persist->mutex */ 1334 dtuple_t *m_replace_tuple; 1335 1336 private: 1337 /** Column number of mysql.innodb_dynamic_metadata.table_id */ 1338 static constexpr unsigned TABLE_ID_COL_NO = 0; 1339 1340 /** Column number of mysql.innodb_dynamic_metadata.version */ 1341 static constexpr unsigned VERSION_COL_NO = 1; 1342 1343 /** Column number of mysql.innodb_dynamic_metadata.metadata */ 1344 static constexpr unsigned METADATA_COL_NO = 2; 1345 1346 /** Number of user columns */ 1347 static constexpr unsigned N_USER_COLS = METADATA_COL_NO + 1; 1348 1349 /** Number of columns */ 1350 static constexpr unsigned N_COLS = N_USER_COLS + DATA_N_SYS_COLS; 1351 1352 /** Clustered index field number of 1353 mysql.innodb_dynamic_metadata.table_id */ 1354 static constexpr unsigned TABLE_ID_FIELD_NO = TABLE_ID_COL_NO; 1355 1356 /** Clustered index field number of 1357 mysql.innodb_dynamic_metadata.version */ 1358 static constexpr unsigned VERSION_FIELD_NO = VERSION_COL_NO + 2; 1359 1360 /** Clustered index field number of 1361 mysql.innodb_dynamic_metadata.metadata 1362 Plusing 2 here skips the DATA_TRX_ID and DATA_ROLL_PTR fields */ 1363 static constexpr unsigned METADATA_FIELD_NO = METADATA_COL_NO + 2; 1364 1365 /** Number of fields in the clustered index */ 1366 static constexpr unsigned N_FIELDS = METADATA_FIELD_NO + 1; 1367 }; 1368 1369 /** Mark the dirty_status of a table as METADATA_DIRTY, and add it to the 1370 dirty_dict_tables list if necessary. 1371 @param[in,out] table table */ 1372 void dict_table_mark_dirty(dict_table_t *table); 1373 #endif /* !UNIV_HOTBACKUP */ 1374 1375 /** Flags an index corrupted in the data dictionary cache only. This 1376 is used to mark a corrupted index when index's own dictionary 1377 is corrupted, and we would force to load such index for repair purpose. 1378 Besides, we have to write a redo log. 1379 We don't want to hold dict_sys->mutex here, so that we can set index as 1380 corrupted in some low-level functions. We would only set the flags from 1381 not corrupted to corrupted when server is running, so it should be safe 1382 to set it directly. 1383 @param[in,out] index index, must not be NULL */ 1384 void dict_set_corrupted(dict_index_t *index) UNIV_COLD; 1385 1386 #ifndef UNIV_HOTBACKUP 1387 /** Check if there is any latest persistent dynamic metadata recorded 1388 in DDTableBuffer table of the specific table. If so, read the metadata and 1389 update the table object accordingly 1390 @param[in] table table object */ 1391 void dict_table_load_dynamic_metadata(dict_table_t *table); 1392 1393 /** Check if any table has any dirty persistent data, if so 1394 write dirty persistent data of table to mysql.innodb_dynamic_metadata 1395 accordingly. */ 1396 void dict_persist_to_dd_table_buffer(); 1397 #endif /* !UNIV_HOTBACKUP */ 1398 1399 /** Apply the persistent dynamic metadata read from redo logs or 1400 DDTableBuffer to corresponding table during recovery. 1401 @param[in,out] table table 1402 @param[in] metadata structure of persistent metadata 1403 @return true if we do apply something to the in-memory table object, 1404 otherwise false */ 1405 bool dict_table_apply_dynamic_metadata(dict_table_t *table, 1406 const PersistentTableMetadata *metadata); 1407 1408 #ifndef UNIV_HOTBACKUP 1409 /** Sets merge_threshold in the SYS_INDEXES 1410 @param[in,out] index index 1411 @param[in] merge_threshold value to set */ 1412 void dict_index_set_merge_threshold(dict_index_t *index, ulint merge_threshold); 1413 1414 #ifdef UNIV_DEBUG 1415 /** Sets merge_threshold for all indexes in dictionary cache for debug. 1416 @param[in] merge_threshold_all value to set for all indexes */ 1417 void dict_set_merge_threshold_all_debug(uint merge_threshold_all); 1418 #endif /* UNIV_DEBUG */ 1419 1420 /** Validate the table flags. 1421 @param[in] flags Table flags 1422 @return true if valid. */ 1423 UNIV_INLINE 1424 bool dict_tf_is_valid(uint32_t flags); 1425 1426 /** Validate both table flags and table flags2 and make sure they 1427 are compatible. 1428 @param[in] flags Table flags 1429 @param[in] flags2 Table flags2 1430 @return true if valid. */ 1431 UNIV_INLINE 1432 bool dict_tf2_is_valid(uint32_t flags, uint32_t flags2); 1433 1434 /** Check if the tablespace for the table has been discarded. 1435 @return true if the tablespace has been discarded. */ 1436 UNIV_INLINE 1437 bool dict_table_is_discarded( 1438 const dict_table_t *table) /*!< in: table to check */ 1439 MY_ATTRIBUTE((warn_unused_result)); 1440 1441 /** Check whether the table is DDTableBuffer. See class DDTableBuffer 1442 @param[in] table table to check 1443 @return true if this is a DDTableBuffer table. */ 1444 UNIV_INLINE 1445 bool dict_table_is_table_buffer(const dict_table_t *table); 1446 1447 /** Check if the table is in a shared tablespace (System or General). 1448 @param[in] table table to check 1449 @return true if table is a shared tablespace, false if not. */ 1450 UNIV_INLINE 1451 bool dict_table_in_shared_tablespace(const dict_table_t *table) 1452 MY_ATTRIBUTE((warn_unused_result)); 1453 1454 /** Check whether locking is disabled for this table. 1455 Currently this is done for intrinsic table as their visibility is limited 1456 to the connection and the DDTableBuffer as it's protected by 1457 dict_persist->mutex. 1458 1459 @param[in] table table to check 1460 @return true if locking is disabled. */ 1461 UNIV_INLINE 1462 bool dict_table_is_locking_disabled(const dict_table_t *table) 1463 MY_ATTRIBUTE((warn_unused_result)); 1464 1465 /** Turn-off redo-logging if temporary table. 1466 @param[in] table table to check 1467 @param[out] mtr mini-transaction */ 1468 UNIV_INLINE 1469 void dict_disable_redo_if_temporary(const dict_table_t *table, mtr_t *mtr); 1470 1471 /** Get table session row-id and increment the row-id counter for next use. 1472 @param[in,out] table table handler 1473 @return next table local row-id. */ 1474 UNIV_INLINE 1475 row_id_t dict_table_get_next_table_sess_row_id(dict_table_t *table); 1476 1477 /** Get table session trx-id and increment the trx-id counter for next use. 1478 @param[in,out] table table handler 1479 @return next table local trx-id. */ 1480 UNIV_INLINE 1481 trx_id_t dict_table_get_next_table_sess_trx_id(dict_table_t *table); 1482 1483 /** Get current session trx-id. 1484 @param[in] table table handler 1485 @return table local trx-id. */ 1486 UNIV_INLINE 1487 trx_id_t dict_table_get_curr_table_sess_trx_id(const dict_table_t *table); 1488 1489 /** This function should be called whenever a page is successfully 1490 compressed. Updates the compression padding information. */ 1491 void dict_index_zip_success( 1492 dict_index_t *index); /*!< in/out: index to be updated. */ 1493 /** This function should be called whenever a page compression attempt 1494 fails. Updates the compression padding information. */ 1495 void dict_index_zip_failure( 1496 dict_index_t *index); /*!< in/out: index to be updated. */ 1497 /** Return the optimal page size, for which page will likely compress. 1498 @return page size beyond which page may not compress*/ 1499 ulint dict_index_zip_pad_optimal_page_size( 1500 dict_index_t *index) /*!< in: index for which page size 1501 is requested */ 1502 MY_ATTRIBUTE((warn_unused_result)); 1503 /** Convert table flag to row format string. 1504 @return row format name */ 1505 const char *dict_tf_to_row_format_string( 1506 uint32_t table_flag); /*!< in: row format setting */ 1507 /** Return maximum size of the node pointer record. 1508 @return maximum size of the record in bytes */ 1509 ulint dict_index_node_ptr_max_size(const dict_index_t *index) /*!< in: index */ 1510 MY_ATTRIBUTE((warn_unused_result)); 1511 1512 /** Get index by first field of the index. 1513 @param[in] table table 1514 @param[in] col_index position of column in table 1515 @return index which is having first field matches with the field present in 1516 field_index position of table */ 1517 UNIV_INLINE 1518 dict_index_t *dict_table_get_index_on_first_col(dict_table_t *table, 1519 ulint col_index); 1520 #endif /* !UNIV_HOTBACKUP */ 1521 1522 /** encode number of columns and number of virtual columns in one 1523 4 bytes value. We could do this because the number of columns in 1524 InnoDB is limited to 1017 1525 @param[in] n_col number of non-virtual column 1526 @param[in] n_v_col number of virtual column 1527 @return encoded value */ 1528 UNIV_INLINE 1529 ulint dict_table_encode_n_col(ulint n_col, ulint n_v_col); 1530 1531 /** Decode number of virtual and non-virtual columns in one 4 bytes value. 1532 @param[in] encoded encoded value 1533 @param[in,out] n_col number of non-virtual column 1534 @param[in,out] n_v_col number of virtual column */ 1535 UNIV_INLINE 1536 void dict_table_decode_n_col(uint32_t encoded, uint32_t *n_col, 1537 uint32_t *n_v_col); 1538 1539 /** Free the virtual column template 1540 @param[in,out] vc_templ virtual column template */ 1541 UNIV_INLINE 1542 void dict_free_vc_templ(dict_vcol_templ_t *vc_templ); 1543 1544 /** Returns a virtual column's name according to its original 1545 MySQL table position. 1546 @param[in] table target table 1547 @param[in] col_nr column number (nth column in the table) 1548 @return column name. */ 1549 const char *dict_table_get_v_col_name_mysql(const dict_table_t *table, 1550 ulint col_nr); 1551 1552 /** Check whether the table have virtual index. 1553 @param[in] table InnoDB table 1554 @return true if the table have virtual index, false otherwise. */ 1555 UNIV_INLINE 1556 bool dict_table_have_virtual_index(dict_table_t *table); 1557 1558 /** Retrieve in-memory index for SDI table. 1559 @param[in] tablespace_id innodb tablespace ID 1560 @return dict_index_t structure or NULL*/ 1561 dict_index_t *dict_sdi_get_index(space_id_t tablespace_id); 1562 1563 /** Retrieve in-memory table object for SDI table. 1564 @param[in] tablespace_id innodb tablespace ID 1565 @param[in] dict_locked true if dict_sys mutex is acquired 1566 @param[in] is_create true when creating SDI Index 1567 @return dict_table_t structure */ 1568 dict_table_t *dict_sdi_get_table(space_id_t tablespace_id, bool dict_locked, 1569 bool is_create); 1570 1571 /** Remove the SDI table from table cache. 1572 @param[in] space_id InnoDB tablespace ID 1573 @param[in] sdi_table SDI table 1574 @param[in] dict_locked true if dict_sys mutex acquired */ 1575 void dict_sdi_remove_from_cache(space_id_t space_id, dict_table_t *sdi_table, 1576 bool dict_locked); 1577 1578 /** Check if the index is SDI index 1579 @param[in] index in-memory index structure 1580 @return true if index is SDI index else false */ 1581 UNIV_INLINE 1582 bool dict_index_is_sdi(const dict_index_t *index); 1583 1584 /** Check if an table id belongs SDI table 1585 @param[in] table_id dict_table_t id 1586 @return true if table_id is SDI table_id else false */ 1587 UNIV_INLINE 1588 bool dict_table_is_sdi(uint64_t table_id); 1589 1590 /** Close SDI table. 1591 @param[in] table the in-meory SDI table object */ 1592 void dict_sdi_close_table(dict_table_t *table); 1593 1594 /** Acquire exclusive MDL on SDI tables. This is acquired to 1595 prevent concurrent DROP table/tablespace when there is purge 1596 happening on SDI table records. Purge will acquired shared 1597 MDL on SDI table. 1598 1599 Exclusive MDL is transactional(released on trx commit). So 1600 for successful acquistion, there should be valid thd with 1601 trx associated. 1602 1603 Acquistion order of SDI MDL and SDI table has to be in same 1604 order: 1605 1606 1. dd_sdi_acquire_exclusive_mdl 1607 2. row_drop_table_from_cache()/innodb_drop_tablespace() 1608 ->dd_sdi_remove_from_cache()->dd_table_open_on_id() 1609 1610 In purge: 1611 1612 1. dd_sdi_acquire_shared_mdl 1613 2. dd_table_open_on_id() 1614 1615 @param[in] thd server thread instance 1616 @param[in] space_id InnoDB tablespace id 1617 @param[in,out] sdi_mdl MDL ticket on SDI table 1618 @retval DB_SUCESS on success 1619 @retval DB_LOCK_WAIT_TIMEOUT on error */ 1620 dberr_t dd_sdi_acquire_exclusive_mdl(THD *thd, space_id_t space_id, 1621 MDL_ticket **sdi_mdl); 1622 1623 /** Acquire shared MDL on SDI tables. This is acquired by purge to 1624 prevent concurrent DROP table/tablespace. 1625 DROP table/tablespace will acquire exclusive MDL on SDI table 1626 1627 Acquistion order of SDI MDL and SDI table has to be in same 1628 order: 1629 1630 1. dd_sdi_acquire_exclusive_mdl 1631 2. row_drop_table_from_cache()/innodb_drop_tablespace() 1632 ->dict_sdi_remove_from_cache()->dd_table_open_on_id() 1633 1634 In purge: 1635 1636 1. dd_sdi_acquire_shared_mdl 1637 2. dd_table_open_on_id() 1638 1639 MDL should be released by caller 1640 @param[in] thd server thread instance 1641 @param[in] space_id InnoDB tablespace id 1642 @param[in,out] sdi_mdl MDL ticket on SDI table 1643 @retval DB_SUCESS on success 1644 @retval DB_LOCK_WAIT_TIMEOUT on error */ 1645 dberr_t dd_sdi_acquire_shared_mdl(THD *thd, space_id_t space_id, 1646 MDL_ticket **sdi_mdl); 1647 1648 /** Check whether the dict_table_t is a partition. 1649 A partitioned table on the SQL level is composed of InnoDB tables, 1650 where each InnoDB table is a [sub]partition including its secondary indexes 1651 which belongs to the partition. 1652 @param[in] table Table to check. 1653 @return true if the dict_table_t is a partition else false. */ 1654 UNIV_INLINE 1655 bool dict_table_is_partition(const dict_table_t *table); 1656 1657 /** Allocate memory for intrinsic cache elements in the index 1658 * @param[in] index index object */ 1659 UNIV_INLINE 1660 void dict_allocate_mem_intrinsic_cache(dict_index_t *index); 1661 1662 /** Evict all tables that are loaded for applying purge. 1663 Since we move the offset of all table ids during upgrade, 1664 these tables cannot exist in cache. Also change table_ids 1665 of SYS_* tables if they are upgraded from earlier versions */ 1666 void dict_upgrade_evict_tables_cache(); 1667 1668 /** @return true if table is InnoDB SYS_* table 1669 @param[in] table_id table id */ 1670 bool dict_table_is_system(table_id_t table_id); 1671 1672 /** Build the table_id array of SYS_* tables. This 1673 array is used to determine if a table is InnoDB SYSTEM 1674 table or not. 1675 @return true if successful, false otherwise */ 1676 bool dict_sys_table_id_build(); 1677 1678 /** Change the table_id of SYS_* tables if they have been created after 1679 an earlier upgrade. This will update the table_id by adding DICT_MAX_DD_TABLES 1680 */ 1681 void dict_table_change_id_sys_tables(); 1682 1683 /** Get the tablespace data directory if set, otherwise empty string. 1684 @return the data directory */ 1685 std::string dict_table_get_datadir(const dict_table_t *table) 1686 MY_ATTRIBUTE((warn_unused_result)); 1687 1688 #include "dict0dict.ic" 1689 1690 #endif 1691