| 1 | /***************************************************************************** |
| 2 | |
| 3 | Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved. |
| 4 | Copyright (c) 2012, Facebook Inc. |
| 5 | Copyright (c) 2013, 2018, 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, Suite 500, Boston, MA 02110-1335 USA |
| 18 | |
| 19 | *****************************************************************************/ |
| 20 | |
| 21 | /**************************************************//** |
| 22 | @file include/dict0mem.h |
| 23 | Data dictionary memory object creation |
| 24 | |
| 25 | Created 1/8/1996 Heikki Tuuri |
| 26 | *******************************************************/ |
| 27 | |
| 28 | #ifndef dict0mem_h |
| 29 | #define dict0mem_h |
| 30 | |
| 31 | #include "univ.i" |
| 32 | #include "dict0types.h" |
| 33 | #include "data0type.h" |
| 34 | #include "mem0mem.h" |
| 35 | #include "row0types.h" |
| 36 | #include "rem0types.h" |
| 37 | #include "btr0types.h" |
| 38 | #include "lock0types.h" |
| 39 | #include "que0types.h" |
| 40 | #include "sync0rw.h" |
| 41 | #include "ut0mem.h" |
| 42 | #include "ut0rnd.h" |
| 43 | #include "ut0byte.h" |
| 44 | #include "hash0hash.h" |
| 45 | #include "trx0types.h" |
| 46 | #include "fts0fts.h" |
| 47 | #include "buf0buf.h" |
| 48 | #include "gis0type.h" |
| 49 | #include "os0once.h" |
| 50 | #include "ut0new.h" |
| 51 | #include "fil0fil.h" |
| 52 | #include "fil0crypt.h" |
| 53 | #include <set> |
| 54 | #include <algorithm> |
| 55 | #include <iterator> |
| 56 | #include <ostream> |
| 57 | |
| 58 | /* Forward declaration. */ |
| 59 | struct ib_rbt_t; |
| 60 | |
| 61 | /** Type flags of an index: OR'ing of the flags is allowed to define a |
| 62 | combination of types */ |
| 63 | /* @{ */ |
| 64 | #define DICT_CLUSTERED 1 /*!< clustered index; for other than |
| 65 | auto-generated clustered indexes, |
| 66 | also DICT_UNIQUE will be set */ |
| 67 | #define DICT_UNIQUE 2 /*!< unique index */ |
| 68 | #define DICT_IBUF 8 /*!< insert buffer tree */ |
| 69 | #define DICT_CORRUPT 16 /*!< bit to store the corrupted flag |
| 70 | in SYS_INDEXES.TYPE */ |
| 71 | #define DICT_FTS 32 /* FTS index; can't be combined with the |
| 72 | other flags */ |
| 73 | #define DICT_SPATIAL 64 /* SPATIAL index; can't be combined with the |
| 74 | other flags */ |
| 75 | #define DICT_VIRTUAL 128 /* Index on Virtual column */ |
| 76 | |
| 77 | #define DICT_IT_BITS 8 /*!< number of bits used for |
| 78 | SYS_INDEXES.TYPE */ |
| 79 | /* @} */ |
| 80 | |
| 81 | #if 0 /* not implemented, retained for history */ |
| 82 | /** Types for a table object */ |
| 83 | #define DICT_TABLE_ORDINARY 1 /*!< ordinary table */ |
| 84 | #define DICT_TABLE_CLUSTER_MEMBER 2 |
| 85 | #define DICT_TABLE_CLUSTER 3 /* this means that the table is |
| 86 | really a cluster definition */ |
| 87 | #endif |
| 88 | |
| 89 | /* Table and tablespace flags are generally not used for the Antelope file |
| 90 | format except for the low order bit, which is used differently depending on |
| 91 | where the flags are stored. |
| 92 | |
| 93 | ==================== Low order flags bit ========================= |
| 94 | | REDUNDANT | COMPACT | COMPRESSED and DYNAMIC |
| 95 | SYS_TABLES.TYPE | 1 | 1 | 1 |
| 96 | dict_table_t::flags | 0 | 1 | 1 |
| 97 | FSP_SPACE_FLAGS | 0 | 0 | 1 |
| 98 | fil_space_t::flags | 0 | 0 | 1 |
| 99 | |
| 100 | Before the 5.1 plugin, SYS_TABLES.TYPE was always DICT_TABLE_ORDINARY (1) |
| 101 | and the tablespace flags field was always 0. In the 5.1 plugin, these fields |
| 102 | were repurposed to identify compressed and dynamic row formats. |
| 103 | |
| 104 | The following types and constants describe the flags found in dict_table_t |
| 105 | and SYS_TABLES.TYPE. Similar flags found in fil_space_t and FSP_SPACE_FLAGS |
| 106 | are described in fsp0fsp.h. */ |
| 107 | |
| 108 | /* @{ */ |
| 109 | /** dict_table_t::flags bit 0 is equal to 0 if the row format = Redundant */ |
| 110 | #define DICT_TF_REDUNDANT 0 /*!< Redundant row format. */ |
| 111 | /** dict_table_t::flags bit 0 is equal to 1 if the row format = Compact */ |
| 112 | #define DICT_TF_COMPACT 1U /*!< Compact row format. */ |
| 113 | |
| 114 | /** This bitmask is used in SYS_TABLES.N_COLS to set and test whether |
| 115 | the Compact page format is used, i.e ROW_FORMAT != REDUNDANT */ |
| 116 | #define DICT_N_COLS_COMPACT 0x80000000UL |
| 117 | |
| 118 | /** Width of the COMPACT flag */ |
| 119 | #define DICT_TF_WIDTH_COMPACT 1 |
| 120 | |
| 121 | /** Width of the ZIP_SSIZE flag */ |
| 122 | #define DICT_TF_WIDTH_ZIP_SSIZE 4 |
| 123 | |
| 124 | /** Width of the ATOMIC_BLOBS flag. The ROW_FORMAT=REDUNDANT and |
| 125 | ROW_FORMAT=COMPACT broke up BLOB and TEXT fields, storing the first 768 bytes |
| 126 | in the clustered index. ROW_FORMAT=DYNAMIC and ROW_FORMAT=COMPRESSED |
| 127 | store the whole blob or text field off-page atomically. |
| 128 | Secondary indexes are created from this external data using row_ext_t |
| 129 | to cache the BLOB prefixes. */ |
| 130 | #define DICT_TF_WIDTH_ATOMIC_BLOBS 1 |
| 131 | |
| 132 | /** If a table is created with the MYSQL option DATA DIRECTORY and |
| 133 | innodb-file-per-table, an older engine will not be able to find that table. |
| 134 | This flag prevents older engines from attempting to open the table and |
| 135 | allows InnoDB to update_create_info() accordingly. */ |
| 136 | #define DICT_TF_WIDTH_DATA_DIR 1 |
| 137 | |
| 138 | /** |
| 139 | Width of the page compression flag |
| 140 | */ |
| 141 | #define DICT_TF_WIDTH_PAGE_COMPRESSION 1 |
| 142 | #define DICT_TF_WIDTH_PAGE_COMPRESSION_LEVEL 4 |
| 143 | |
| 144 | /** |
| 145 | The NO_ROLLBACK flag (3=yes; the values 1,2 used stand for |
| 146 | ATOMIC_WRITES=ON and ATOMIC_WRITES=OFF between MariaDB 10.1.0 and 10.2.3) |
| 147 | */ |
| 148 | #define DICT_TF_WIDTH_NO_ROLLBACK 2 |
| 149 | |
| 150 | /** Width of all the currently known table flags */ |
| 151 | #define DICT_TF_BITS (DICT_TF_WIDTH_COMPACT \ |
| 152 | + DICT_TF_WIDTH_ZIP_SSIZE \ |
| 153 | + DICT_TF_WIDTH_ATOMIC_BLOBS \ |
| 154 | + DICT_TF_WIDTH_DATA_DIR \ |
| 155 | + DICT_TF_WIDTH_PAGE_COMPRESSION \ |
| 156 | + DICT_TF_WIDTH_PAGE_COMPRESSION_LEVEL \ |
| 157 | + DICT_TF_WIDTH_NO_ROLLBACK) |
| 158 | |
| 159 | /** Zero relative shift position of the COMPACT field */ |
| 160 | #define DICT_TF_POS_COMPACT 0 |
| 161 | /** Zero relative shift position of the ZIP_SSIZE field */ |
| 162 | #define DICT_TF_POS_ZIP_SSIZE (DICT_TF_POS_COMPACT \ |
| 163 | + DICT_TF_WIDTH_COMPACT) |
| 164 | /** Zero relative shift position of the ATOMIC_BLOBS field */ |
| 165 | #define DICT_TF_POS_ATOMIC_BLOBS (DICT_TF_POS_ZIP_SSIZE \ |
| 166 | + DICT_TF_WIDTH_ZIP_SSIZE) |
| 167 | /** Zero relative shift position of the DATA_DIR field */ |
| 168 | #define DICT_TF_POS_DATA_DIR (DICT_TF_POS_ATOMIC_BLOBS \ |
| 169 | + DICT_TF_WIDTH_ATOMIC_BLOBS) |
| 170 | /** Zero relative shift position of the PAGE_COMPRESSION field */ |
| 171 | #define DICT_TF_POS_PAGE_COMPRESSION (DICT_TF_POS_DATA_DIR \ |
| 172 | + DICT_TF_WIDTH_DATA_DIR) |
| 173 | /** Zero relative shift position of the PAGE_COMPRESSION_LEVEL field */ |
| 174 | #define DICT_TF_POS_PAGE_COMPRESSION_LEVEL (DICT_TF_POS_PAGE_COMPRESSION \ |
| 175 | + DICT_TF_WIDTH_PAGE_COMPRESSION) |
| 176 | /** Zero relative shift position of the NO_ROLLBACK field */ |
| 177 | #define DICT_TF_POS_NO_ROLLBACK (DICT_TF_POS_PAGE_COMPRESSION_LEVEL \ |
| 178 | + DICT_TF_WIDTH_PAGE_COMPRESSION_LEVEL) |
| 179 | #define DICT_TF_POS_UNUSED (DICT_TF_POS_NO_ROLLBACK \ |
| 180 | + DICT_TF_WIDTH_NO_ROLLBACK) |
| 181 | |
| 182 | /** Bit mask of the COMPACT field */ |
| 183 | #define DICT_TF_MASK_COMPACT \ |
| 184 | ((~(~0U << DICT_TF_WIDTH_COMPACT)) \ |
| 185 | << DICT_TF_POS_COMPACT) |
| 186 | /** Bit mask of the ZIP_SSIZE field */ |
| 187 | #define DICT_TF_MASK_ZIP_SSIZE \ |
| 188 | ((~(~0U << DICT_TF_WIDTH_ZIP_SSIZE)) \ |
| 189 | << DICT_TF_POS_ZIP_SSIZE) |
| 190 | /** Bit mask of the ATOMIC_BLOBS field */ |
| 191 | #define DICT_TF_MASK_ATOMIC_BLOBS \ |
| 192 | ((~(~0U << DICT_TF_WIDTH_ATOMIC_BLOBS)) \ |
| 193 | << DICT_TF_POS_ATOMIC_BLOBS) |
| 194 | /** Bit mask of the DATA_DIR field */ |
| 195 | #define DICT_TF_MASK_DATA_DIR \ |
| 196 | ((~(~0U << DICT_TF_WIDTH_DATA_DIR)) \ |
| 197 | << DICT_TF_POS_DATA_DIR) |
| 198 | /** Bit mask of the PAGE_COMPRESSION field */ |
| 199 | #define DICT_TF_MASK_PAGE_COMPRESSION \ |
| 200 | ((~(~0U << DICT_TF_WIDTH_PAGE_COMPRESSION)) \ |
| 201 | << DICT_TF_POS_PAGE_COMPRESSION) |
| 202 | /** Bit mask of the PAGE_COMPRESSION_LEVEL field */ |
| 203 | #define DICT_TF_MASK_PAGE_COMPRESSION_LEVEL \ |
| 204 | ((~(~0U << DICT_TF_WIDTH_PAGE_COMPRESSION_LEVEL)) \ |
| 205 | << DICT_TF_POS_PAGE_COMPRESSION_LEVEL) |
| 206 | /** Bit mask of the NO_ROLLBACK field */ |
| 207 | #define DICT_TF_MASK_NO_ROLLBACK \ |
| 208 | ((~(~0U << DICT_TF_WIDTH_NO_ROLLBACK)) \ |
| 209 | << DICT_TF_POS_NO_ROLLBACK) |
| 210 | |
| 211 | /** Return the value of the COMPACT field */ |
| 212 | #define DICT_TF_GET_COMPACT(flags) \ |
| 213 | ((flags & DICT_TF_MASK_COMPACT) \ |
| 214 | >> DICT_TF_POS_COMPACT) |
| 215 | /** Return the value of the ZIP_SSIZE field */ |
| 216 | #define DICT_TF_GET_ZIP_SSIZE(flags) \ |
| 217 | ((flags & DICT_TF_MASK_ZIP_SSIZE) \ |
| 218 | >> DICT_TF_POS_ZIP_SSIZE) |
| 219 | /** Return the value of the ATOMIC_BLOBS field */ |
| 220 | #define DICT_TF_HAS_ATOMIC_BLOBS(flags) \ |
| 221 | ((flags & DICT_TF_MASK_ATOMIC_BLOBS) \ |
| 222 | >> DICT_TF_POS_ATOMIC_BLOBS) |
| 223 | /** Return the value of the DATA_DIR field */ |
| 224 | #define DICT_TF_HAS_DATA_DIR(flags) \ |
| 225 | ((flags & DICT_TF_MASK_DATA_DIR) \ |
| 226 | >> DICT_TF_POS_DATA_DIR) |
| 227 | /** Return the value of the PAGE_COMPRESSION field */ |
| 228 | #define DICT_TF_GET_PAGE_COMPRESSION(flags) \ |
| 229 | ((flags & DICT_TF_MASK_PAGE_COMPRESSION) \ |
| 230 | >> DICT_TF_POS_PAGE_COMPRESSION) |
| 231 | /** Return the value of the PAGE_COMPRESSION_LEVEL field */ |
| 232 | #define DICT_TF_GET_PAGE_COMPRESSION_LEVEL(flags) \ |
| 233 | ((flags & DICT_TF_MASK_PAGE_COMPRESSION_LEVEL) \ |
| 234 | >> DICT_TF_POS_PAGE_COMPRESSION_LEVEL) |
| 235 | |
| 236 | /* @} */ |
| 237 | |
| 238 | /** @brief Table Flags set number 2. |
| 239 | |
| 240 | These flags will be stored in SYS_TABLES.MIX_LEN. All unused flags |
| 241 | will be written as 0. The column may contain garbage for tables |
| 242 | created with old versions of InnoDB that only implemented |
| 243 | ROW_FORMAT=REDUNDANT. InnoDB engines do not check these flags |
| 244 | for unknown bits in order to protect backward incompatibility. */ |
| 245 | /* @{ */ |
| 246 | /** Total number of bits in table->flags2. */ |
| 247 | #define DICT_TF2_BITS 7 |
| 248 | #define DICT_TF2_UNUSED_BIT_MASK (~0U << DICT_TF2_BITS) |
| 249 | #define DICT_TF2_BIT_MASK ~DICT_TF2_UNUSED_BIT_MASK |
| 250 | |
| 251 | /** TEMPORARY; TRUE for tables from CREATE TEMPORARY TABLE. */ |
| 252 | #define DICT_TF2_TEMPORARY 1U |
| 253 | |
| 254 | /** The table has an internal defined DOC ID column */ |
| 255 | #define DICT_TF2_FTS_HAS_DOC_ID 2U |
| 256 | |
| 257 | /** The table has an FTS index */ |
| 258 | #define DICT_TF2_FTS 4U |
| 259 | |
| 260 | /** Need to add Doc ID column for FTS index build. |
| 261 | This is a transient bit for index build */ |
| 262 | #define DICT_TF2_FTS_ADD_DOC_ID 8U |
| 263 | |
| 264 | /** This bit is used during table creation to indicate that it will |
| 265 | use its own tablespace instead of the system tablespace. */ |
| 266 | #define DICT_TF2_USE_FILE_PER_TABLE 16U |
| 267 | |
| 268 | /** Set when we discard/detach the tablespace */ |
| 269 | #define DICT_TF2_DISCARDED 32U |
| 270 | |
| 271 | /** This bit is set if all aux table names (both common tables and |
| 272 | index tables) of a FTS table are in HEX format. */ |
| 273 | #define DICT_TF2_FTS_AUX_HEX_NAME 64U |
| 274 | |
| 275 | /* @} */ |
| 276 | |
| 277 | #define DICT_TF2_FLAG_SET(table, flag) \ |
| 278 | (table->flags2 |= (flag)) |
| 279 | |
| 280 | #define DICT_TF2_FLAG_IS_SET(table, flag) \ |
| 281 | (table->flags2 & (flag)) |
| 282 | |
| 283 | #define DICT_TF2_FLAG_UNSET(table, flag) \ |
| 284 | (table->flags2 &= ~(flag)) |
| 285 | |
| 286 | /** Tables could be chained together with Foreign key constraint. When |
| 287 | first load the parent table, we would load all of its descedents. |
| 288 | This could result in rescursive calls and out of stack error eventually. |
| 289 | DICT_FK_MAX_RECURSIVE_LOAD defines the maximum number of recursive loads, |
| 290 | when exceeded, the child table will not be loaded. It will be loaded when |
| 291 | the foreign constraint check needs to be run. */ |
| 292 | #define DICT_FK_MAX_RECURSIVE_LOAD 20 |
| 293 | |
| 294 | /** Similarly, when tables are chained together with foreign key constraints |
| 295 | with on cascading delete/update clause, delete from parent table could |
| 296 | result in recursive cascading calls. This defines the maximum number of |
| 297 | such cascading deletes/updates allowed. When exceeded, the delete from |
| 298 | parent table will fail, and user has to drop excessive foreign constraint |
| 299 | before proceeds. */ |
| 300 | #define FK_MAX_CASCADE_DEL 15 |
| 301 | |
| 302 | /**********************************************************************//** |
| 303 | Creates a table memory object. |
| 304 | @return own: table object */ |
| 305 | dict_table_t* |
| 306 | dict_mem_table_create( |
| 307 | /*==================*/ |
| 308 | const char* name, /*!< in: table name */ |
| 309 | fil_space_t* space, /*!< in: tablespace */ |
| 310 | ulint n_cols, /*!< in: total number of columns |
| 311 | including virtual and non-virtual |
| 312 | columns */ |
| 313 | ulint n_v_cols, /*!< in: number of virtual columns */ |
| 314 | ulint flags, /*!< in: table flags */ |
| 315 | ulint flags2); /*!< in: table flags2 */ |
| 316 | /****************************************************************//** |
| 317 | Free a table memory object. */ |
| 318 | void |
| 319 | dict_mem_table_free( |
| 320 | /*================*/ |
| 321 | dict_table_t* table); /*!< in: table */ |
| 322 | /**********************************************************************//** |
| 323 | Adds a column definition to a table. */ |
| 324 | void |
| 325 | dict_mem_table_add_col( |
| 326 | /*===================*/ |
| 327 | dict_table_t* table, /*!< in: table */ |
| 328 | mem_heap_t* heap, /*!< in: temporary memory heap, or NULL */ |
| 329 | const char* name, /*!< in: column name, or NULL */ |
| 330 | ulint mtype, /*!< in: main datatype */ |
| 331 | ulint prtype, /*!< in: precise type */ |
| 332 | ulint len) /*!< in: precision */ |
| 333 | MY_ATTRIBUTE((nonnull(1))); |
| 334 | /** Adds a virtual column definition to a table. |
| 335 | @param[in,out] table table |
| 336 | @param[in] heap temporary memory heap, or NULL. It is |
| 337 | used to store name when we have not finished |
| 338 | adding all columns. When all columns are |
| 339 | added, the whole name will copy to memory from |
| 340 | table->heap |
| 341 | @param[in] name column name |
| 342 | @param[in] mtype main datatype |
| 343 | @param[in] prtype precise type |
| 344 | @param[in] len length |
| 345 | @param[in] pos position in a table |
| 346 | @param[in] num_base number of base columns |
| 347 | @return the virtual column definition */ |
| 348 | dict_v_col_t* |
| 349 | dict_mem_table_add_v_col( |
| 350 | dict_table_t* table, |
| 351 | mem_heap_t* heap, |
| 352 | const char* name, |
| 353 | ulint mtype, |
| 354 | ulint prtype, |
| 355 | ulint len, |
| 356 | ulint pos, |
| 357 | ulint num_base); |
| 358 | |
| 359 | /** Adds a stored column definition to a table. |
| 360 | @param[in] table table |
| 361 | @param[in] num_base number of base columns. */ |
| 362 | void |
| 363 | dict_mem_table_add_s_col( |
| 364 | dict_table_t* table, |
| 365 | ulint num_base); |
| 366 | |
| 367 | /**********************************************************************//** |
| 368 | Renames a column of a table in the data dictionary cache. */ |
| 369 | void |
| 370 | dict_mem_table_col_rename( |
| 371 | /*======================*/ |
| 372 | dict_table_t* table, /*!< in/out: table */ |
| 373 | ulint nth_col,/*!< in: column index */ |
| 374 | const char* from, /*!< in: old column name */ |
| 375 | const char* to, /*!< in: new column name */ |
| 376 | bool is_virtual); |
| 377 | /*!< in: if this is a virtual column */ |
| 378 | /**********************************************************************//** |
| 379 | This function populates a dict_col_t memory structure with |
| 380 | supplied information. */ |
| 381 | void |
| 382 | dict_mem_fill_column_struct( |
| 383 | /*========================*/ |
| 384 | dict_col_t* column, /*!< out: column struct to be |
| 385 | filled */ |
| 386 | ulint col_pos, /*!< in: column position */ |
| 387 | ulint mtype, /*!< in: main data type */ |
| 388 | ulint prtype, /*!< in: precise type */ |
| 389 | ulint col_len); /*!< in: column length */ |
| 390 | /**********************************************************************//** |
| 391 | This function poplulates a dict_index_t index memory structure with |
| 392 | supplied information. */ |
| 393 | UNIV_INLINE |
| 394 | void |
| 395 | dict_mem_fill_index_struct( |
| 396 | /*=======================*/ |
| 397 | dict_index_t* index, /*!< out: index to be filled */ |
| 398 | mem_heap_t* heap, /*!< in: memory heap */ |
| 399 | const char* index_name, /*!< in: index name */ |
| 400 | ulint type, /*!< in: DICT_UNIQUE, |
| 401 | DICT_CLUSTERED, ... ORed */ |
| 402 | ulint n_fields); /*!< in: number of fields */ |
| 403 | /**********************************************************************//** |
| 404 | Creates an index memory object. |
| 405 | @return own: index object */ |
| 406 | dict_index_t* |
| 407 | dict_mem_index_create( |
| 408 | /*==================*/ |
| 409 | dict_table_t* table, /*!< in: table */ |
| 410 | const char* index_name, /*!< in: index name */ |
| 411 | ulint type, /*!< in: DICT_UNIQUE, |
| 412 | DICT_CLUSTERED, ... ORed */ |
| 413 | ulint n_fields); /*!< in: number of fields */ |
| 414 | /**********************************************************************//** |
| 415 | Adds a field definition to an index. NOTE: does not take a copy |
| 416 | of the column name if the field is a column. The memory occupied |
| 417 | by the column name may be released only after publishing the index. */ |
| 418 | void |
| 419 | dict_mem_index_add_field( |
| 420 | /*=====================*/ |
| 421 | dict_index_t* index, /*!< in: index */ |
| 422 | const char* name, /*!< in: column name */ |
| 423 | ulint prefix_len); /*!< in: 0 or the column prefix length |
| 424 | in a MySQL index like |
| 425 | INDEX (textcol(25)) */ |
| 426 | /**********************************************************************//** |
| 427 | Frees an index memory object. */ |
| 428 | void |
| 429 | dict_mem_index_free( |
| 430 | /*================*/ |
| 431 | dict_index_t* index); /*!< in: index */ |
| 432 | /**********************************************************************//** |
| 433 | Creates and initializes a foreign constraint memory object. |
| 434 | @return own: foreign constraint struct */ |
| 435 | dict_foreign_t* |
| 436 | dict_mem_foreign_create(void); |
| 437 | /*=========================*/ |
| 438 | |
| 439 | /**********************************************************************//** |
| 440 | Sets the foreign_table_name_lookup pointer based on the value of |
| 441 | lower_case_table_names. If that is 0 or 1, foreign_table_name_lookup |
| 442 | will point to foreign_table_name. If 2, then another string is |
| 443 | allocated from the heap and set to lower case. */ |
| 444 | void |
| 445 | dict_mem_foreign_table_name_lookup_set( |
| 446 | /*===================================*/ |
| 447 | dict_foreign_t* foreign, /*!< in/out: foreign struct */ |
| 448 | ibool do_alloc); /*!< in: is an alloc needed */ |
| 449 | |
| 450 | /**********************************************************************//** |
| 451 | Sets the referenced_table_name_lookup pointer based on the value of |
| 452 | lower_case_table_names. If that is 0 or 1, referenced_table_name_lookup |
| 453 | will point to referenced_table_name. If 2, then another string is |
| 454 | allocated from the heap and set to lower case. */ |
| 455 | void |
| 456 | dict_mem_referenced_table_name_lookup_set( |
| 457 | /*======================================*/ |
| 458 | dict_foreign_t* foreign, /*!< in/out: foreign struct */ |
| 459 | ibool do_alloc); /*!< in: is an alloc needed */ |
| 460 | |
| 461 | /** Fills the dependent virtual columns in a set. |
| 462 | Reason for being dependent are |
| 463 | 1) FK can be present on base column of virtual columns |
| 464 | 2) FK can be present on column which is a part of virtual index |
| 465 | @param[in,out] foreign foreign key information. */ |
| 466 | void |
| 467 | dict_mem_foreign_fill_vcol_set( |
| 468 | dict_foreign_t* foreign); |
| 469 | |
| 470 | /** Fill virtual columns set in each fk constraint present in the table. |
| 471 | @param[in,out] table innodb table object. */ |
| 472 | void |
| 473 | dict_mem_table_fill_foreign_vcol_set( |
| 474 | dict_table_t* table); |
| 475 | |
| 476 | /** Free the vcol_set from all foreign key constraint on the table. |
| 477 | @param[in,out] table innodb table object. */ |
| 478 | void |
| 479 | dict_mem_table_free_foreign_vcol_set( |
| 480 | dict_table_t* table); |
| 481 | |
| 482 | /** Create a temporary tablename like "#sql-ibtid-inc where |
| 483 | tid = the Table ID |
| 484 | inc = a randomly initialized number that is incremented for each file |
| 485 | The table ID is a 64 bit integer, can use up to 20 digits, and is |
| 486 | initialized at bootstrap. The second number is 32 bits, can use up to 10 |
| 487 | digits, and is initialized at startup to a randomly distributed number. |
| 488 | It is hoped that the combination of these two numbers will provide a |
| 489 | reasonably unique temporary file name. |
| 490 | @param[in] heap A memory heap |
| 491 | @param[in] dbtab Table name in the form database/table name |
| 492 | @param[in] id Table id |
| 493 | @return A unique temporary tablename suitable for InnoDB use */ |
| 494 | char* |
| 495 | dict_mem_create_temporary_tablename( |
| 496 | mem_heap_t* heap, |
| 497 | const char* dbtab, |
| 498 | table_id_t id); |
| 499 | |
| 500 | /** Initialize dict memory variables */ |
| 501 | void |
| 502 | dict_mem_init(void); |
| 503 | |
| 504 | /** SQL identifier name wrapper for pretty-printing */ |
| 505 | class id_name_t |
| 506 | { |
| 507 | public: |
| 508 | /** Default constructor */ |
| 509 | id_name_t() |
| 510 | : m_name() |
| 511 | {} |
| 512 | /** Constructor |
| 513 | @param[in] name identifier to assign */ |
| 514 | explicit id_name_t( |
| 515 | const char* name) |
| 516 | : m_name(name) |
| 517 | {} |
| 518 | |
| 519 | /** Assignment operator |
| 520 | @param[in] name identifier to assign */ |
| 521 | id_name_t& operator=( |
| 522 | const char* name) |
| 523 | { |
| 524 | m_name = name; |
| 525 | return(*this); |
| 526 | } |
| 527 | |
| 528 | /** Implicit type conversion |
| 529 | @return the name */ |
| 530 | operator const char*() const |
| 531 | { |
| 532 | return(m_name); |
| 533 | } |
| 534 | |
| 535 | /** Explicit type conversion |
| 536 | @return the name */ |
| 537 | const char* operator()() const |
| 538 | { |
| 539 | return(m_name); |
| 540 | } |
| 541 | |
| 542 | private: |
| 543 | /** The name in internal representation */ |
| 544 | const char* m_name; |
| 545 | }; |
| 546 | |
| 547 | /** Data structure for a column in a table */ |
| 548 | struct dict_col_t{ |
| 549 | /*----------------------*/ |
| 550 | /** The following are copied from dtype_t, |
| 551 | so that all bit-fields can be packed tightly. */ |
| 552 | /* @{ */ |
| 553 | unsigned prtype:32; /*!< precise type; MySQL data |
| 554 | type, charset code, flags to |
| 555 | indicate nullability, |
| 556 | signedness, whether this is a |
| 557 | binary string, whether this is |
| 558 | a true VARCHAR where MySQL |
| 559 | uses 2 bytes to store the length */ |
| 560 | unsigned mtype:8; /*!< main data type */ |
| 561 | |
| 562 | /* the remaining fields do not affect alphabetical ordering: */ |
| 563 | |
| 564 | unsigned len:16; /*!< length; for MySQL data this |
| 565 | is field->pack_length(), |
| 566 | except that for a >= 5.0.3 |
| 567 | type true VARCHAR this is the |
| 568 | maximum byte length of the |
| 569 | string data (in addition to |
| 570 | the string, MySQL uses 1 or 2 |
| 571 | bytes to store the string length) */ |
| 572 | |
| 573 | unsigned mbminlen:3; /*!< minimum length of a |
| 574 | character, in bytes */ |
| 575 | unsigned mbmaxlen:3; /*!< maximum length of a |
| 576 | character, in bytes */ |
| 577 | /*----------------------*/ |
| 578 | /* End of definitions copied from dtype_t */ |
| 579 | /* @} */ |
| 580 | |
| 581 | unsigned ind:10; /*!< table column position |
| 582 | (starting from 0) */ |
| 583 | unsigned ord_part:1; /*!< nonzero if this column |
| 584 | appears in the ordering fields |
| 585 | of an index */ |
| 586 | unsigned max_prefix:12; /*!< maximum index prefix length on |
| 587 | this column. Our current max limit is |
| 588 | 3072 (REC_VERSION_56_MAX_INDEX_COL_LEN) |
| 589 | bytes. */ |
| 590 | |
| 591 | /** Data for instantly added columns */ |
| 592 | struct { |
| 593 | /** original default value of instantly added column */ |
| 594 | const void* data; |
| 595 | /** len of data, or UNIV_SQL_DEFAULT if unavailable */ |
| 596 | ulint len; |
| 597 | } def_val; |
| 598 | |
| 599 | /** Retrieve the column name. |
| 600 | @param[in] table table name */ |
| 601 | const char* name(const dict_table_t& table) const; |
| 602 | |
| 603 | /** @return whether this is a virtual column */ |
| 604 | bool is_virtual() const { return prtype & DATA_VIRTUAL; } |
| 605 | /** @return whether NULL is an allowed value for this column */ |
| 606 | bool is_nullable() const { return !(prtype & DATA_NOT_NULL); } |
| 607 | |
| 608 | /** @return whether table of this system field is TRX_ID-based */ |
| 609 | bool vers_native() const |
| 610 | { |
| 611 | ut_ad(vers_sys_start() || vers_sys_end()); |
| 612 | ut_ad(mtype == DATA_INT || mtype == DATA_FIXBINARY); |
| 613 | return mtype == DATA_INT; |
| 614 | } |
| 615 | /** @return whether this is system versioned */ |
| 616 | bool is_versioned() const { return !(~prtype & DATA_VERSIONED); } |
| 617 | /** @return whether this is the system version start */ |
| 618 | bool vers_sys_start() const |
| 619 | { |
| 620 | return (prtype & DATA_VERSIONED) == DATA_VERS_START; |
| 621 | } |
| 622 | /** @return whether this is the system version end */ |
| 623 | bool vers_sys_end() const |
| 624 | { |
| 625 | return (prtype & DATA_VERSIONED) == DATA_VERS_END; |
| 626 | } |
| 627 | |
| 628 | /** @return whether this is an instantly-added column */ |
| 629 | bool is_instant() const |
| 630 | { |
| 631 | DBUG_ASSERT(def_val.len != UNIV_SQL_DEFAULT || !def_val.data); |
| 632 | return def_val.len != UNIV_SQL_DEFAULT; |
| 633 | } |
| 634 | /** Get the default value of an instantly-added column. |
| 635 | @param[out] len value length (in bytes), or UNIV_SQL_NULL |
| 636 | @return default value |
| 637 | @retval NULL if the default value is SQL NULL (len=UNIV_SQL_NULL) */ |
| 638 | const byte* instant_value(ulint* len) const |
| 639 | { |
| 640 | DBUG_ASSERT(is_instant()); |
| 641 | *len = def_val.len; |
| 642 | return static_cast<const byte*>(def_val.data); |
| 643 | } |
| 644 | |
| 645 | /** Remove the 'instant ADD' status of the column */ |
| 646 | void remove_instant() |
| 647 | { |
| 648 | DBUG_ASSERT(is_instant()); |
| 649 | def_val.len = UNIV_SQL_DEFAULT; |
| 650 | def_val.data = NULL; |
| 651 | } |
| 652 | }; |
| 653 | |
| 654 | /** Index information put in a list of virtual column structure. Index |
| 655 | id and virtual column position in the index will be logged. |
| 656 | There can be multiple entries for a given index, with a different position. */ |
| 657 | struct dict_v_idx_t { |
| 658 | /** active index on the column */ |
| 659 | dict_index_t* index; |
| 660 | |
| 661 | /** position in this index */ |
| 662 | ulint nth_field; |
| 663 | |
| 664 | dict_v_idx_t(dict_index_t* index, ulint nth_field) |
| 665 | : index(index), nth_field(nth_field) {} |
| 666 | }; |
| 667 | |
| 668 | /** Index list to put in dict_v_col_t */ |
| 669 | typedef std::list<dict_v_idx_t, ut_allocator<dict_v_idx_t> > dict_v_idx_list; |
| 670 | |
| 671 | /** Data structure for a virtual column in a table */ |
| 672 | struct dict_v_col_t{ |
| 673 | /** column structure */ |
| 674 | dict_col_t m_col; |
| 675 | |
| 676 | /** array of base column ptr */ |
| 677 | dict_col_t** base_col; |
| 678 | |
| 679 | /** number of base column */ |
| 680 | ulint num_base; |
| 681 | |
| 682 | /** column pos in table */ |
| 683 | ulint v_pos; |
| 684 | |
| 685 | /** Virtual index list, and column position in the index, |
| 686 | the allocated memory is not from table->heap, nor it is |
| 687 | tracked by dict_sys->size */ |
| 688 | dict_v_idx_list* v_indexes; |
| 689 | |
| 690 | }; |
| 691 | |
| 692 | /** Data structure for newly added virtual column in a table */ |
| 693 | struct dict_add_v_col_t{ |
| 694 | /** number of new virtual column */ |
| 695 | ulint n_v_col; |
| 696 | |
| 697 | /** column structures */ |
| 698 | const dict_v_col_t* v_col; |
| 699 | |
| 700 | /** new col names */ |
| 701 | const char** v_col_name; |
| 702 | }; |
| 703 | |
| 704 | /** Data structure for a stored column in a table. */ |
| 705 | struct dict_s_col_t { |
| 706 | /** Stored column ptr */ |
| 707 | dict_col_t* m_col; |
| 708 | /** array of base col ptr */ |
| 709 | dict_col_t** base_col; |
| 710 | /** number of base columns */ |
| 711 | ulint num_base; |
| 712 | /** column pos in table */ |
| 713 | ulint s_pos; |
| 714 | }; |
| 715 | |
| 716 | /** list to put stored column for create_table_info_t */ |
| 717 | typedef std::list<dict_s_col_t, ut_allocator<dict_s_col_t> > dict_s_col_list; |
| 718 | |
| 719 | /** @brief DICT_ANTELOPE_MAX_INDEX_COL_LEN is measured in bytes and |
| 720 | is the maximum indexed column length (or indexed prefix length) in |
| 721 | ROW_FORMAT=REDUNDANT and ROW_FORMAT=COMPACT. Also, in any format, |
| 722 | any fixed-length field that is longer than this will be encoded as |
| 723 | a variable-length field. |
| 724 | |
| 725 | It is set to 3*256, so that one can create a column prefix index on |
| 726 | 256 characters of a TEXT or VARCHAR column also in the UTF-8 |
| 727 | charset. In that charset, a character may take at most 3 bytes. This |
| 728 | constant MUST NOT BE CHANGED, or the compatibility of InnoDB data |
| 729 | files would be at risk! */ |
| 730 | #define DICT_ANTELOPE_MAX_INDEX_COL_LEN REC_ANTELOPE_MAX_INDEX_COL_LEN |
| 731 | |
| 732 | /** Find out maximum indexed column length by its table format. |
| 733 | For ROW_FORMAT=REDUNDANT and ROW_FORMAT=COMPACT, the maximum |
| 734 | field length is REC_ANTELOPE_MAX_INDEX_COL_LEN - 1 (767). For |
| 735 | ROW_FORMAT=COMPRESSED and ROW_FORMAT=DYNAMIC, the length could |
| 736 | be REC_VERSION_56_MAX_INDEX_COL_LEN (3072) bytes */ |
| 737 | #define DICT_MAX_FIELD_LEN_BY_FORMAT(table) \ |
| 738 | (dict_table_has_atomic_blobs(table) \ |
| 739 | ? REC_VERSION_56_MAX_INDEX_COL_LEN \ |
| 740 | : REC_ANTELOPE_MAX_INDEX_COL_LEN - 1) |
| 741 | |
| 742 | #define DICT_MAX_FIELD_LEN_BY_FORMAT_FLAG(flags) \ |
| 743 | (DICT_TF_HAS_ATOMIC_BLOBS(flags) \ |
| 744 | ? REC_VERSION_56_MAX_INDEX_COL_LEN \ |
| 745 | : REC_ANTELOPE_MAX_INDEX_COL_LEN - 1) |
| 746 | |
| 747 | /** Defines the maximum fixed length column size */ |
| 748 | #define DICT_MAX_FIXED_COL_LEN DICT_ANTELOPE_MAX_INDEX_COL_LEN |
| 749 | |
| 750 | #ifdef WITH_WSREP |
| 751 | #define WSREP_MAX_SUPPORTED_KEY_LENGTH 3500 |
| 752 | #endif /* WITH_WSREP */ |
| 753 | |
| 754 | /** Data structure for a field in an index */ |
| 755 | struct dict_field_t{ |
| 756 | dict_col_t* col; /*!< pointer to the table column */ |
| 757 | id_name_t name; /*!< name of the column */ |
| 758 | unsigned prefix_len:12; /*!< 0 or the length of the column |
| 759 | prefix in bytes in a MySQL index of |
| 760 | type, e.g., INDEX (textcol(25)); |
| 761 | must be smaller than |
| 762 | DICT_MAX_FIELD_LEN_BY_FORMAT; |
| 763 | NOTE that in the UTF-8 charset, MySQL |
| 764 | sets this to (mbmaxlen * the prefix len) |
| 765 | in UTF-8 chars */ |
| 766 | unsigned fixed_len:10; /*!< 0 or the fixed length of the |
| 767 | column if smaller than |
| 768 | DICT_ANTELOPE_MAX_INDEX_COL_LEN */ |
| 769 | |
| 770 | /** Check whether two index fields are equivalent. |
| 771 | @param[in] old the other index field |
| 772 | @return whether the index fields are equivalent */ |
| 773 | bool same(const dict_field_t& other) const |
| 774 | { |
| 775 | return(prefix_len == other.prefix_len |
| 776 | && fixed_len == other.fixed_len); |
| 777 | } |
| 778 | }; |
| 779 | |
| 780 | /**********************************************************************//** |
| 781 | PADDING HEURISTIC BASED ON LINEAR INCREASE OF PADDING TO AVOID |
| 782 | COMPRESSION FAILURES |
| 783 | (Note: this is relevant only for compressed indexes) |
| 784 | GOAL: Avoid compression failures by maintaining information about the |
| 785 | compressibility of data. If data is not very compressible then leave |
| 786 | some extra space 'padding' in the uncompressed page making it more |
| 787 | likely that compression of less than fully packed uncompressed page will |
| 788 | succeed. |
| 789 | |
| 790 | This padding heuristic works by increasing the pad linearly until the |
| 791 | desired failure rate is reached. A "round" is a fixed number of |
| 792 | compression operations. |
| 793 | After each round, the compression failure rate for that round is |
| 794 | computed. If the failure rate is too high, then padding is incremented |
| 795 | by a fixed value, otherwise it's left intact. |
| 796 | If the compression failure is lower than the desired rate for a fixed |
| 797 | number of consecutive rounds, then the padding is decreased by a fixed |
| 798 | value. This is done to prevent overshooting the padding value, |
| 799 | and to accommodate the possible change in data compressibility. */ |
| 800 | |
| 801 | /** Number of zip ops in one round. */ |
| 802 | #define ZIP_PAD_ROUND_LEN (128) |
| 803 | |
| 804 | /** Number of successful rounds after which the padding is decreased */ |
| 805 | #define ZIP_PAD_SUCCESSFUL_ROUND_LIMIT (5) |
| 806 | |
| 807 | /** Amount by which padding is increased. */ |
| 808 | #define ZIP_PAD_INCR (128) |
| 809 | |
| 810 | /** Percentage of compression failures that are allowed in a single |
| 811 | round */ |
| 812 | extern ulong zip_failure_threshold_pct; |
| 813 | |
| 814 | /** Maximum percentage of a page that can be allowed as a pad to avoid |
| 815 | compression failures */ |
| 816 | extern ulong zip_pad_max; |
| 817 | |
| 818 | /** Data structure to hold information about about how much space in |
| 819 | an uncompressed page should be left as padding to avoid compression |
| 820 | failures. This estimate is based on a self-adapting heuristic. */ |
| 821 | struct zip_pad_info_t { |
| 822 | SysMutex* mutex; /*!< mutex protecting the info */ |
| 823 | ulint pad; /*!< number of bytes used as pad */ |
| 824 | ulint success;/*!< successful compression ops during |
| 825 | current round */ |
| 826 | ulint failure;/*!< failed compression ops during |
| 827 | current round */ |
| 828 | ulint n_rounds;/*!< number of currently successful |
| 829 | rounds */ |
| 830 | volatile os_once::state_t |
| 831 | mutex_created; |
| 832 | /*!< Creation state of mutex member */ |
| 833 | }; |
| 834 | |
| 835 | /** Number of samples of data size kept when page compression fails for |
| 836 | a certain index.*/ |
| 837 | #define STAT_DEFRAG_DATA_SIZE_N_SAMPLE 10 |
| 838 | |
| 839 | /** "GEN_CLUST_INDEX" is the name reserved for InnoDB default |
| 840 | system clustered index when there is no primary key. */ |
| 841 | const char innobase_index_reserve_name[] = "GEN_CLUST_INDEX" ; |
| 842 | |
| 843 | /* Estimated number of offsets in records (based on columns) |
| 844 | to start with. */ |
| 845 | #define OFFS_IN_REC_NORMAL_SIZE 100 |
| 846 | |
| 847 | /** Data structure for an index. Most fields will be |
| 848 | initialized to 0, NULL or FALSE in dict_mem_index_create(). */ |
| 849 | struct dict_index_t{ |
| 850 | index_id_t id; /*!< id of the index */ |
| 851 | mem_heap_t* heap; /*!< memory heap */ |
| 852 | id_name_t name; /*!< index name */ |
| 853 | dict_table_t* table; /*!< back pointer to table */ |
| 854 | unsigned page:32;/*!< index tree root page number */ |
| 855 | unsigned merge_threshold:6; |
| 856 | /*!< In the pessimistic delete, if the page |
| 857 | data size drops below this limit in percent, |
| 858 | merging it to a neighbor is tried */ |
| 859 | # define DICT_INDEX_MERGE_THRESHOLD_DEFAULT 50 |
| 860 | unsigned type:DICT_IT_BITS; |
| 861 | /*!< index type (DICT_CLUSTERED, DICT_UNIQUE, |
| 862 | DICT_IBUF, DICT_CORRUPT) */ |
| 863 | #define MAX_KEY_LENGTH_BITS 12 |
| 864 | unsigned trx_id_offset:MAX_KEY_LENGTH_BITS; |
| 865 | /*!< position of the trx id column |
| 866 | in a clustered index record, if the fields |
| 867 | before it are known to be of a fixed size, |
| 868 | 0 otherwise */ |
| 869 | #if (1<<MAX_KEY_LENGTH_BITS) < HA_MAX_KEY_LENGTH |
| 870 | # error (1<<MAX_KEY_LENGTH_BITS) < HA_MAX_KEY_LENGTH |
| 871 | #endif |
| 872 | unsigned n_user_defined_cols:10; |
| 873 | /*!< number of columns the user defined to |
| 874 | be in the index: in the internal |
| 875 | representation we add more columns */ |
| 876 | unsigned nulls_equal:1; |
| 877 | /*!< if true, SQL NULL == SQL NULL */ |
| 878 | #ifdef BTR_CUR_HASH_ADAPT |
| 879 | #ifdef MYSQL_INDEX_DISABLE_AHI |
| 880 | unsigned disable_ahi:1; |
| 881 | /*!< whether to disable the |
| 882 | adaptive hash index. |
| 883 | Maybe this could be disabled for |
| 884 | temporary tables? */ |
| 885 | #endif |
| 886 | #endif /* BTR_CUR_HASH_ADAPT */ |
| 887 | unsigned n_uniq:10;/*!< number of fields from the beginning |
| 888 | which are enough to determine an index |
| 889 | entry uniquely */ |
| 890 | unsigned n_def:10;/*!< number of fields defined so far */ |
| 891 | unsigned n_fields:10;/*!< number of fields in the index */ |
| 892 | unsigned n_nullable:10;/*!< number of nullable fields */ |
| 893 | unsigned n_core_fields:10;/*!< number of fields in the index |
| 894 | (before the first time of instant add columns) */ |
| 895 | /** number of bytes of null bits in ROW_FORMAT!=REDUNDANT node pointer |
| 896 | records; usually equal to UT_BITS_IN_BYTES(n_nullable), but |
| 897 | can be less in clustered indexes with instant ADD COLUMN */ |
| 898 | unsigned n_core_null_bytes:8; |
| 899 | /** magic value signalling that n_core_null_bytes was not |
| 900 | initialized yet */ |
| 901 | static const unsigned NO_CORE_NULL_BYTES = 0xff; |
| 902 | /** The clustered index ID of the hard-coded SYS_INDEXES table. */ |
| 903 | static const unsigned DICT_INDEXES_ID = 3; |
| 904 | unsigned cached:1;/*!< TRUE if the index object is in the |
| 905 | dictionary cache */ |
| 906 | unsigned to_be_dropped:1; |
| 907 | /*!< TRUE if the index is to be dropped; |
| 908 | protected by dict_operation_lock */ |
| 909 | unsigned online_status:2; |
| 910 | /*!< enum online_index_status. |
| 911 | Transitions from ONLINE_INDEX_COMPLETE (to |
| 912 | ONLINE_INDEX_CREATION) are protected |
| 913 | by dict_operation_lock and |
| 914 | dict_sys->mutex. Other changes are |
| 915 | protected by index->lock. */ |
| 916 | unsigned uncommitted:1; |
| 917 | /*!< a flag that is set for secondary indexes |
| 918 | that have not been committed to the |
| 919 | data dictionary yet */ |
| 920 | |
| 921 | #ifdef UNIV_DEBUG |
| 922 | /** whether this is a dummy index object */ |
| 923 | bool is_dummy; |
| 924 | uint32_t magic_n;/*!< magic number */ |
| 925 | /** Value of dict_index_t::magic_n */ |
| 926 | # define DICT_INDEX_MAGIC_N 76789786 |
| 927 | #endif |
| 928 | dict_field_t* fields; /*!< array of field descriptions */ |
| 929 | st_mysql_ftparser* |
| 930 | parser; /*!< fulltext parser plugin */ |
| 931 | bool has_new_v_col; |
| 932 | /*!< whether it has a newly added virtual |
| 933 | column in ALTER */ |
| 934 | bool index_fts_syncing;/*!< Whether the fts index is |
| 935 | still syncing in the background; |
| 936 | FIXME: remove this and use MDL */ |
| 937 | UT_LIST_NODE_T(dict_index_t) |
| 938 | indexes;/*!< list of indexes of the table */ |
| 939 | #ifdef BTR_CUR_ADAPT |
| 940 | btr_search_t* search_info; |
| 941 | /*!< info used in optimistic searches */ |
| 942 | #endif /* BTR_CUR_ADAPT */ |
| 943 | row_log_t* online_log; |
| 944 | /*!< the log of modifications |
| 945 | during online index creation; |
| 946 | valid when online_status is |
| 947 | ONLINE_INDEX_CREATION */ |
| 948 | /*----------------------*/ |
| 949 | /** Statistics for query optimization */ |
| 950 | /* @{ */ |
| 951 | ib_uint64_t* stat_n_diff_key_vals; |
| 952 | /*!< approximate number of different |
| 953 | key values for this index, for each |
| 954 | n-column prefix where 1 <= n <= |
| 955 | dict_get_n_unique(index) (the array is |
| 956 | indexed from 0 to n_uniq-1); we |
| 957 | periodically calculate new |
| 958 | estimates */ |
| 959 | ib_uint64_t* stat_n_sample_sizes; |
| 960 | /*!< number of pages that were sampled |
| 961 | to calculate each of stat_n_diff_key_vals[], |
| 962 | e.g. stat_n_sample_sizes[3] pages were sampled |
| 963 | to get the number stat_n_diff_key_vals[3]. */ |
| 964 | ib_uint64_t* stat_n_non_null_key_vals; |
| 965 | /* approximate number of non-null key values |
| 966 | for this index, for each column where |
| 967 | 1 <= n <= dict_get_n_unique(index) (the array |
| 968 | is indexed from 0 to n_uniq-1); This |
| 969 | is used when innodb_stats_method is |
| 970 | "nulls_ignored". */ |
| 971 | ulint stat_index_size; |
| 972 | /*!< approximate index size in |
| 973 | database pages */ |
| 974 | ulint stat_n_leaf_pages; |
| 975 | /*!< approximate number of leaf pages in the |
| 976 | index tree */ |
| 977 | bool stats_error_printed; |
| 978 | /*!< has persistent statistics error printed |
| 979 | for this index ? */ |
| 980 | /* @} */ |
| 981 | /** Statistics for defragmentation, these numbers are estimations and |
| 982 | could be very inaccurate at certain times, e.g. right after restart, |
| 983 | during defragmentation, etc. */ |
| 984 | /* @{ */ |
| 985 | ulint stat_defrag_modified_counter; |
| 986 | ulint stat_defrag_n_pages_freed; |
| 987 | /* number of pages freed by defragmentation. */ |
| 988 | ulint stat_defrag_n_page_split; |
| 989 | /* number of page splits since last full index |
| 990 | defragmentation. */ |
| 991 | ulint stat_defrag_data_size_sample[STAT_DEFRAG_DATA_SIZE_N_SAMPLE]; |
| 992 | /* data size when compression failure happened |
| 993 | the most recent 10 times. */ |
| 994 | ulint stat_defrag_sample_next_slot; |
| 995 | /* in which slot the next sample should be |
| 996 | saved. */ |
| 997 | /* @} */ |
| 998 | rtr_ssn_t rtr_ssn;/*!< Node sequence number for RTree */ |
| 999 | rtr_info_track_t* |
| 1000 | rtr_track;/*!< tracking all R-Tree search cursors */ |
| 1001 | trx_id_t trx_id; /*!< id of the transaction that created this |
| 1002 | index, or 0 if the index existed |
| 1003 | when InnoDB was started up */ |
| 1004 | zip_pad_info_t zip_pad;/*!< Information about state of |
| 1005 | compression failures and successes */ |
| 1006 | rw_lock_t lock; /*!< read-write lock protecting the |
| 1007 | upper levels of the index tree */ |
| 1008 | |
| 1009 | /** Determine if the index has been committed to the |
| 1010 | data dictionary. |
| 1011 | @return whether the index definition has been committed */ |
| 1012 | bool is_committed() const |
| 1013 | { |
| 1014 | ut_ad(!uncommitted || !(type & DICT_CLUSTERED)); |
| 1015 | return(UNIV_LIKELY(!uncommitted)); |
| 1016 | } |
| 1017 | |
| 1018 | /** Flag an index committed or uncommitted. |
| 1019 | @param[in] committed whether the index is committed */ |
| 1020 | void set_committed(bool committed) |
| 1021 | { |
| 1022 | ut_ad(!to_be_dropped); |
| 1023 | ut_ad(committed || !(type & DICT_CLUSTERED)); |
| 1024 | uncommitted = !committed; |
| 1025 | } |
| 1026 | |
| 1027 | /** Notify that the index pages are going to be modified. |
| 1028 | @param[in,out] mtr mini-transaction */ |
| 1029 | inline void set_modified(mtr_t& mtr) const; |
| 1030 | |
| 1031 | /** @return whether this index is readable |
| 1032 | @retval true normally |
| 1033 | @retval false if this is a single-table tablespace |
| 1034 | and the .ibd file is missing, or a |
| 1035 | page cannot be read or decrypted */ |
| 1036 | inline bool is_readable() const; |
| 1037 | |
| 1038 | /** @return whether instant ADD COLUMN is in effect */ |
| 1039 | inline bool is_instant() const; |
| 1040 | |
| 1041 | /** @return whether the index is the primary key index |
| 1042 | (not the clustered index of the change buffer) */ |
| 1043 | bool is_primary() const |
| 1044 | { |
| 1045 | return DICT_CLUSTERED == (type & (DICT_CLUSTERED | DICT_IBUF)); |
| 1046 | } |
| 1047 | |
| 1048 | /** @return whether the index is corrupted */ |
| 1049 | inline bool is_corrupted() const; |
| 1050 | |
| 1051 | /** Determine how many fields of a given prefix can be set NULL. |
| 1052 | @param[in] n_prefix number of fields in the prefix |
| 1053 | @return number of fields 0..n_prefix-1 that can be set NULL */ |
| 1054 | unsigned get_n_nullable(ulint n_prefix) const |
| 1055 | { |
| 1056 | DBUG_ASSERT(n_prefix > 0); |
| 1057 | DBUG_ASSERT(n_prefix <= n_fields); |
| 1058 | unsigned n = n_nullable; |
| 1059 | for (; n_prefix < n_fields; n_prefix++) { |
| 1060 | const dict_col_t* col = fields[n_prefix].col; |
| 1061 | DBUG_ASSERT(!col->is_virtual()); |
| 1062 | n -= col->is_nullable(); |
| 1063 | } |
| 1064 | DBUG_ASSERT(n < n_def); |
| 1065 | return n; |
| 1066 | } |
| 1067 | |
| 1068 | /** Get the default value of an instantly-added clustered index field. |
| 1069 | @param[in] n instantly added field position |
| 1070 | @param[out] len value length (in bytes), or UNIV_SQL_NULL |
| 1071 | @return default value |
| 1072 | @retval NULL if the default value is SQL NULL (len=UNIV_SQL_NULL) */ |
| 1073 | const byte* instant_field_value(ulint n, ulint* len) const |
| 1074 | { |
| 1075 | DBUG_ASSERT(is_instant() || id == DICT_INDEXES_ID); |
| 1076 | DBUG_ASSERT(n + (id == DICT_INDEXES_ID) >= n_core_fields); |
| 1077 | DBUG_ASSERT(n < n_fields); |
| 1078 | return fields[n].col->instant_value(len); |
| 1079 | } |
| 1080 | |
| 1081 | /** Adjust clustered index metadata for instant ADD COLUMN. |
| 1082 | @param[in] clustered index definition after instant ADD COLUMN */ |
| 1083 | void instant_add_field(const dict_index_t& instant); |
| 1084 | |
| 1085 | /** Remove the 'instant ADD' status of a clustered index. |
| 1086 | Protected by index root page x-latch or table X-lock. */ |
| 1087 | void remove_instant() |
| 1088 | { |
| 1089 | DBUG_ASSERT(is_primary()); |
| 1090 | if (!is_instant()) { |
| 1091 | return; |
| 1092 | } |
| 1093 | for (unsigned i = n_core_fields; i < n_fields; i++) { |
| 1094 | fields[i].col->remove_instant(); |
| 1095 | } |
| 1096 | n_core_fields = n_fields; |
| 1097 | n_core_null_bytes = UT_BITS_IN_BYTES(unsigned(n_nullable)); |
| 1098 | } |
| 1099 | |
| 1100 | /** Check if record in clustered index is historical row. |
| 1101 | @param[in] rec clustered row |
| 1102 | @param[in] offsets offsets |
| 1103 | @return true if row is historical */ |
| 1104 | bool |
| 1105 | vers_history_row(const rec_t* rec, const ulint* offsets); |
| 1106 | |
| 1107 | /** Check if record in secondary index is historical row. |
| 1108 | @param[in] rec record in a secondary index |
| 1109 | @param[out] history_row true if row is historical |
| 1110 | @return true on error */ |
| 1111 | bool |
| 1112 | vers_history_row(const rec_t* rec, bool &history_row); |
| 1113 | }; |
| 1114 | |
| 1115 | /** The status of online index creation */ |
| 1116 | enum online_index_status { |
| 1117 | /** the index is complete and ready for access */ |
| 1118 | ONLINE_INDEX_COMPLETE = 0, |
| 1119 | /** the index is being created, online |
| 1120 | (allowing concurrent modifications) */ |
| 1121 | ONLINE_INDEX_CREATION, |
| 1122 | /** secondary index creation was aborted and the index |
| 1123 | should be dropped as soon as index->table->n_ref_count reaches 0, |
| 1124 | or online table rebuild was aborted and the clustered index |
| 1125 | of the original table should soon be restored to |
| 1126 | ONLINE_INDEX_COMPLETE */ |
| 1127 | ONLINE_INDEX_ABORTED, |
| 1128 | /** the online index creation was aborted, the index was |
| 1129 | dropped from the data dictionary and the tablespace, and it |
| 1130 | should be dropped from the data dictionary cache as soon as |
| 1131 | index->table->n_ref_count reaches 0. */ |
| 1132 | ONLINE_INDEX_ABORTED_DROPPED |
| 1133 | }; |
| 1134 | |
| 1135 | /** Set to store the virtual columns which are affected by Foreign |
| 1136 | key constraint. */ |
| 1137 | typedef std::set<dict_v_col_t*, std::less<dict_v_col_t*>, |
| 1138 | ut_allocator<dict_v_col_t*> > dict_vcol_set; |
| 1139 | |
| 1140 | /** Data structure for a foreign key constraint; an example: |
| 1141 | FOREIGN KEY (A, B) REFERENCES TABLE2 (C, D). Most fields will be |
| 1142 | initialized to 0, NULL or FALSE in dict_mem_foreign_create(). */ |
| 1143 | struct dict_foreign_t{ |
| 1144 | mem_heap_t* heap; /*!< this object is allocated from |
| 1145 | this memory heap */ |
| 1146 | char* id; /*!< id of the constraint as a |
| 1147 | null-terminated string */ |
| 1148 | unsigned n_fields:10; /*!< number of indexes' first fields |
| 1149 | for which the foreign key |
| 1150 | constraint is defined: we allow the |
| 1151 | indexes to contain more fields than |
| 1152 | mentioned in the constraint, as long |
| 1153 | as the first fields are as mentioned */ |
| 1154 | unsigned type:6; /*!< 0 or DICT_FOREIGN_ON_DELETE_CASCADE |
| 1155 | or DICT_FOREIGN_ON_DELETE_SET_NULL */ |
| 1156 | char* foreign_table_name;/*!< foreign table name */ |
| 1157 | char* foreign_table_name_lookup; |
| 1158 | /*!< foreign table name used for dict lookup */ |
| 1159 | dict_table_t* foreign_table; /*!< table where the foreign key is */ |
| 1160 | const char** foreign_col_names;/*!< names of the columns in the |
| 1161 | foreign key */ |
| 1162 | char* referenced_table_name;/*!< referenced table name */ |
| 1163 | char* referenced_table_name_lookup; |
| 1164 | /*!< referenced table name for dict lookup*/ |
| 1165 | dict_table_t* referenced_table;/*!< table where the referenced key |
| 1166 | is */ |
| 1167 | const char** referenced_col_names;/*!< names of the referenced |
| 1168 | columns in the referenced table */ |
| 1169 | dict_index_t* foreign_index; /*!< foreign index; we require that |
| 1170 | both tables contain explicitly defined |
| 1171 | indexes for the constraint: InnoDB |
| 1172 | does not generate new indexes |
| 1173 | implicitly */ |
| 1174 | dict_index_t* referenced_index;/*!< referenced index */ |
| 1175 | |
| 1176 | dict_vcol_set* v_cols; /*!< set of virtual columns affected |
| 1177 | by foreign key constraint. */ |
| 1178 | }; |
| 1179 | |
| 1180 | std::ostream& |
| 1181 | operator<< (std::ostream& out, const dict_foreign_t& foreign); |
| 1182 | |
| 1183 | struct dict_foreign_print { |
| 1184 | |
| 1185 | dict_foreign_print(std::ostream& out) |
| 1186 | : m_out(out) |
| 1187 | {} |
| 1188 | |
| 1189 | void operator()(const dict_foreign_t* foreign) { |
| 1190 | m_out << *foreign; |
| 1191 | } |
| 1192 | private: |
| 1193 | std::ostream& m_out; |
| 1194 | }; |
| 1195 | |
| 1196 | /** Compare two dict_foreign_t objects using their ids. Used in the ordering |
| 1197 | of dict_table_t::foreign_set and dict_table_t::referenced_set. It returns |
| 1198 | true if the first argument is considered to go before the second in the |
| 1199 | strict weak ordering it defines, and false otherwise. */ |
| 1200 | struct dict_foreign_compare { |
| 1201 | |
| 1202 | bool operator()( |
| 1203 | const dict_foreign_t* lhs, |
| 1204 | const dict_foreign_t* rhs) const |
| 1205 | { |
| 1206 | return(ut_strcmp(lhs->id, rhs->id) < 0); |
| 1207 | } |
| 1208 | }; |
| 1209 | |
| 1210 | /** A function object to find a foreign key with the given index as the |
| 1211 | referenced index. Return the foreign key with matching criteria or NULL */ |
| 1212 | struct dict_foreign_with_index { |
| 1213 | |
| 1214 | dict_foreign_with_index(const dict_index_t* index) |
| 1215 | : m_index(index) |
| 1216 | {} |
| 1217 | |
| 1218 | bool operator()(const dict_foreign_t* foreign) const |
| 1219 | { |
| 1220 | return(foreign->referenced_index == m_index); |
| 1221 | } |
| 1222 | |
| 1223 | const dict_index_t* m_index; |
| 1224 | }; |
| 1225 | |
| 1226 | #ifdef WITH_WSREP |
| 1227 | /** A function object to find a foreign key with the given index as the |
| 1228 | foreign index. Return the foreign key with matching criteria or NULL */ |
| 1229 | struct dict_foreign_with_foreign_index { |
| 1230 | |
| 1231 | dict_foreign_with_foreign_index(const dict_index_t* index) |
| 1232 | : m_index(index) |
| 1233 | {} |
| 1234 | |
| 1235 | bool operator()(const dict_foreign_t* foreign) const |
| 1236 | { |
| 1237 | return(foreign->foreign_index == m_index); |
| 1238 | } |
| 1239 | |
| 1240 | const dict_index_t* m_index; |
| 1241 | }; |
| 1242 | #endif |
| 1243 | |
| 1244 | /* A function object to check if the foreign constraint is between different |
| 1245 | tables. Returns true if foreign key constraint is between different tables, |
| 1246 | false otherwise. */ |
| 1247 | struct dict_foreign_different_tables { |
| 1248 | |
| 1249 | bool operator()(const dict_foreign_t* foreign) const |
| 1250 | { |
| 1251 | return(foreign->foreign_table != foreign->referenced_table); |
| 1252 | } |
| 1253 | }; |
| 1254 | |
| 1255 | /** A function object to check if the foreign key constraint has the same |
| 1256 | name as given. If the full name of the foreign key constraint doesn't match, |
| 1257 | then, check if removing the database name from the foreign key constraint |
| 1258 | matches. Return true if it matches, false otherwise. */ |
| 1259 | struct dict_foreign_matches_id { |
| 1260 | |
| 1261 | dict_foreign_matches_id(const char* id) |
| 1262 | : m_id(id) |
| 1263 | {} |
| 1264 | |
| 1265 | bool operator()(const dict_foreign_t* foreign) const |
| 1266 | { |
| 1267 | if (0 == innobase_strcasecmp(foreign->id, m_id)) { |
| 1268 | return(true); |
| 1269 | } |
| 1270 | if (const char* pos = strchr(foreign->id, '/')) { |
| 1271 | if (0 == innobase_strcasecmp(m_id, pos + 1)) { |
| 1272 | return(true); |
| 1273 | } |
| 1274 | } |
| 1275 | return(false); |
| 1276 | } |
| 1277 | |
| 1278 | const char* m_id; |
| 1279 | }; |
| 1280 | |
| 1281 | typedef std::set< |
| 1282 | dict_foreign_t*, |
| 1283 | dict_foreign_compare, |
| 1284 | ut_allocator<dict_foreign_t*> > dict_foreign_set; |
| 1285 | |
| 1286 | std::ostream& |
| 1287 | operator<< (std::ostream& out, const dict_foreign_set& fk_set); |
| 1288 | |
| 1289 | /** Function object to check if a foreign key object is there |
| 1290 | in the given foreign key set or not. It returns true if the |
| 1291 | foreign key is not found, false otherwise */ |
| 1292 | struct dict_foreign_not_exists { |
| 1293 | dict_foreign_not_exists(const dict_foreign_set& obj_) |
| 1294 | : m_foreigns(obj_) |
| 1295 | {} |
| 1296 | |
| 1297 | /* Return true if the given foreign key is not found */ |
| 1298 | bool operator()(dict_foreign_t* const & foreign) const { |
| 1299 | return(m_foreigns.find(foreign) == m_foreigns.end()); |
| 1300 | } |
| 1301 | private: |
| 1302 | const dict_foreign_set& m_foreigns; |
| 1303 | }; |
| 1304 | |
| 1305 | /** Validate the search order in the foreign key set. |
| 1306 | @param[in] fk_set the foreign key set to be validated |
| 1307 | @return true if search order is fine in the set, false otherwise. */ |
| 1308 | bool |
| 1309 | dict_foreign_set_validate( |
| 1310 | const dict_foreign_set& fk_set); |
| 1311 | |
| 1312 | /** Validate the search order in the foreign key sets of the table |
| 1313 | (foreign_set and referenced_set). |
| 1314 | @param[in] table table whose foreign key sets are to be validated |
| 1315 | @return true if foreign key sets are fine, false otherwise. */ |
| 1316 | bool |
| 1317 | dict_foreign_set_validate( |
| 1318 | const dict_table_t& table); |
| 1319 | |
| 1320 | /*********************************************************************//** |
| 1321 | Frees a foreign key struct. */ |
| 1322 | inline |
| 1323 | void |
| 1324 | dict_foreign_free( |
| 1325 | /*==============*/ |
| 1326 | dict_foreign_t* foreign) /*!< in, own: foreign key struct */ |
| 1327 | { |
| 1328 | if (foreign->v_cols != NULL) { |
| 1329 | UT_DELETE(foreign->v_cols); |
| 1330 | } |
| 1331 | |
| 1332 | mem_heap_free(foreign->heap); |
| 1333 | } |
| 1334 | |
| 1335 | /** The destructor will free all the foreign key constraints in the set |
| 1336 | by calling dict_foreign_free() on each of the foreign key constraints. |
| 1337 | This is used to free the allocated memory when a local set goes out |
| 1338 | of scope. */ |
| 1339 | struct dict_foreign_set_free { |
| 1340 | |
| 1341 | dict_foreign_set_free(const dict_foreign_set& foreign_set) |
| 1342 | : m_foreign_set(foreign_set) |
| 1343 | {} |
| 1344 | |
| 1345 | ~dict_foreign_set_free() |
| 1346 | { |
| 1347 | std::for_each(m_foreign_set.begin(), |
| 1348 | m_foreign_set.end(), |
| 1349 | dict_foreign_free); |
| 1350 | } |
| 1351 | |
| 1352 | const dict_foreign_set& m_foreign_set; |
| 1353 | }; |
| 1354 | |
| 1355 | /** The flags for ON_UPDATE and ON_DELETE can be ORed; the default is that |
| 1356 | a foreign key constraint is enforced, therefore RESTRICT just means no flag */ |
| 1357 | /* @{ */ |
| 1358 | #define DICT_FOREIGN_ON_DELETE_CASCADE 1U /*!< ON DELETE CASCADE */ |
| 1359 | #define DICT_FOREIGN_ON_DELETE_SET_NULL 2U /*!< ON UPDATE SET NULL */ |
| 1360 | #define DICT_FOREIGN_ON_UPDATE_CASCADE 4U /*!< ON DELETE CASCADE */ |
| 1361 | #define DICT_FOREIGN_ON_UPDATE_SET_NULL 8U /*!< ON UPDATE SET NULL */ |
| 1362 | #define DICT_FOREIGN_ON_DELETE_NO_ACTION 16U /*!< ON DELETE NO ACTION */ |
| 1363 | #define DICT_FOREIGN_ON_UPDATE_NO_ACTION 32U /*!< ON UPDATE NO ACTION */ |
| 1364 | /* @} */ |
| 1365 | |
| 1366 | /** Display an identifier. |
| 1367 | @param[in,out] s output stream |
| 1368 | @param[in] id_name SQL identifier (other than table name) |
| 1369 | @return the output stream */ |
| 1370 | std::ostream& |
| 1371 | operator<<( |
| 1372 | std::ostream& s, |
| 1373 | const id_name_t& id_name); |
| 1374 | |
| 1375 | /** Display a table name. |
| 1376 | @param[in,out] s output stream |
| 1377 | @param[in] table_name table name |
| 1378 | @return the output stream */ |
| 1379 | std::ostream& |
| 1380 | operator<<( |
| 1381 | std::ostream& s, |
| 1382 | const table_name_t& table_name); |
| 1383 | |
| 1384 | /** List of locks that different transactions have acquired on a table. This |
| 1385 | list has a list node that is embedded in a nested union/structure. We have to |
| 1386 | generate a specific template for it. */ |
| 1387 | |
| 1388 | typedef ut_list_base<lock_t, ut_list_node<lock_t> lock_table_t::*> |
| 1389 | table_lock_list_t; |
| 1390 | |
| 1391 | /** mysql template structure defined in row0mysql.cc */ |
| 1392 | struct mysql_row_templ_t; |
| 1393 | |
| 1394 | /** Structure defines template related to virtual columns and |
| 1395 | their base columns */ |
| 1396 | struct dict_vcol_templ_t { |
| 1397 | /** number of regular columns */ |
| 1398 | ulint n_col; |
| 1399 | |
| 1400 | /** number of virtual columns */ |
| 1401 | ulint n_v_col; |
| 1402 | |
| 1403 | /** array of templates for virtual col and their base columns */ |
| 1404 | mysql_row_templ_t** vtempl; |
| 1405 | |
| 1406 | /** table's database name */ |
| 1407 | std::string db_name; |
| 1408 | |
| 1409 | /** table name */ |
| 1410 | std::string tb_name; |
| 1411 | |
| 1412 | /** MySQL record length */ |
| 1413 | ulint rec_len; |
| 1414 | |
| 1415 | /** default column value if any */ |
| 1416 | byte* default_rec; |
| 1417 | |
| 1418 | /** cached MySQL TABLE object */ |
| 1419 | TABLE* mysql_table; |
| 1420 | |
| 1421 | /** when mysql_table was cached */ |
| 1422 | uint64_t mysql_table_query_id; |
| 1423 | |
| 1424 | dict_vcol_templ_t() : vtempl(0), mysql_table_query_id(~0ULL) {} |
| 1425 | }; |
| 1426 | |
| 1427 | /** These are used when MySQL FRM and InnoDB data dictionary are |
| 1428 | in inconsistent state. */ |
| 1429 | typedef enum { |
| 1430 | DICT_FRM_CONSISTENT = 0, /*!< Consistent state */ |
| 1431 | DICT_FRM_NO_PK = 1, /*!< MySQL has no primary key |
| 1432 | but InnoDB dictionary has |
| 1433 | non-generated one. */ |
| 1434 | DICT_NO_PK_FRM_HAS = 2, /*!< MySQL has primary key but |
| 1435 | InnoDB dictionary has not. */ |
| 1436 | DICT_FRM_INCONSISTENT_KEYS = 3 /*!< Key count mismatch */ |
| 1437 | } dict_frm_t; |
| 1438 | |
| 1439 | /** Data structure for a database table. Most fields will be |
| 1440 | initialized to 0, NULL or FALSE in dict_mem_table_create(). */ |
| 1441 | struct dict_table_t { |
| 1442 | |
| 1443 | /** Get reference count. |
| 1444 | @return current value of n_ref_count */ |
| 1445 | inline ulint get_ref_count() const; |
| 1446 | |
| 1447 | /** Acquire the table handle. */ |
| 1448 | inline void acquire(); |
| 1449 | |
| 1450 | /** Release the table handle. |
| 1451 | @return whether the last handle was released */ |
| 1452 | inline bool release(); |
| 1453 | |
| 1454 | /** @return whether the table supports transactions */ |
| 1455 | bool no_rollback() const |
| 1456 | { |
| 1457 | return !(~unsigned(flags) & DICT_TF_MASK_NO_ROLLBACK); |
| 1458 | } |
| 1459 | /** @return whether this is a temporary table */ |
| 1460 | bool is_temporary() const |
| 1461 | { |
| 1462 | return flags2 & DICT_TF2_TEMPORARY; |
| 1463 | } |
| 1464 | |
| 1465 | /** @return whether this table is readable |
| 1466 | @retval true normally |
| 1467 | @retval false if this is a single-table tablespace |
| 1468 | and the .ibd file is missing, or a |
| 1469 | page cannot be read or decrypted */ |
| 1470 | bool is_readable() const |
| 1471 | { |
| 1472 | ut_ad(file_unreadable || space); |
| 1473 | return(UNIV_LIKELY(!file_unreadable)); |
| 1474 | } |
| 1475 | |
| 1476 | /** @return whether instant ADD COLUMN is in effect */ |
| 1477 | bool is_instant() const |
| 1478 | { |
| 1479 | return(UT_LIST_GET_FIRST(indexes)->is_instant()); |
| 1480 | } |
| 1481 | |
| 1482 | /** @return whether the table supports instant ADD COLUMN */ |
| 1483 | bool supports_instant() const |
| 1484 | { |
| 1485 | return(!(flags & DICT_TF_MASK_ZIP_SSIZE)); |
| 1486 | } |
| 1487 | |
| 1488 | /** Adjust metadata for instant ADD COLUMN. |
| 1489 | @param[in] table table definition after instant ADD COLUMN */ |
| 1490 | void instant_add_column(const dict_table_t& table); |
| 1491 | |
| 1492 | /** Roll back instant_add_column(). |
| 1493 | @param[in] old_n_cols original n_cols |
| 1494 | @param[in] old_cols original cols |
| 1495 | @param[in] old_col_names original col_names */ |
| 1496 | void rollback_instant( |
| 1497 | unsigned old_n_cols, |
| 1498 | dict_col_t* old_cols, |
| 1499 | const char* old_col_names); |
| 1500 | |
| 1501 | /** Trim the instantly added columns when an insert into SYS_COLUMNS |
| 1502 | is rolled back during ALTER TABLE or recovery. |
| 1503 | @param[in] n number of surviving non-system columns */ |
| 1504 | void rollback_instant(unsigned n); |
| 1505 | |
| 1506 | /** Add the table definition to the data dictionary cache */ |
| 1507 | void add_to_cache(); |
| 1508 | |
| 1509 | bool versioned() const { return vers_start || vers_end; } |
| 1510 | bool versioned_by_id() const |
| 1511 | { |
| 1512 | return vers_start && cols[vers_start].mtype == DATA_INT; |
| 1513 | } |
| 1514 | |
| 1515 | void inc_fk_checks() |
| 1516 | { |
| 1517 | #ifdef UNIV_DEBUG |
| 1518 | lint fk_checks= (lint) |
| 1519 | #endif |
| 1520 | my_atomic_addlint(&n_foreign_key_checks_running, 1); |
| 1521 | ut_ad(fk_checks >= 0); |
| 1522 | } |
| 1523 | void dec_fk_checks() |
| 1524 | { |
| 1525 | #ifdef UNIV_DEBUG |
| 1526 | lint fk_checks= (lint) |
| 1527 | #endif |
| 1528 | my_atomic_addlint(&n_foreign_key_checks_running, ulint(-1)); |
| 1529 | ut_ad(fk_checks > 0); |
| 1530 | } |
| 1531 | |
| 1532 | /** Id of the table. */ |
| 1533 | table_id_t id; |
| 1534 | |
| 1535 | /** Memory heap. If you allocate from this heap after the table has |
| 1536 | been created then be sure to account the allocation into |
| 1537 | dict_sys->size. When closing the table we do something like |
| 1538 | dict_sys->size -= mem_heap_get_size(table->heap) and if that is going |
| 1539 | to become negative then we would assert. Something like this should do: |
| 1540 | old_size = mem_heap_get_size() |
| 1541 | mem_heap_alloc() |
| 1542 | new_size = mem_heap_get_size() |
| 1543 | dict_sys->size += new_size - old_size. */ |
| 1544 | mem_heap_t* heap; |
| 1545 | |
| 1546 | /** Table name. */ |
| 1547 | table_name_t name; |
| 1548 | |
| 1549 | /** NULL or the directory path specified by DATA DIRECTORY. */ |
| 1550 | char* data_dir_path; |
| 1551 | |
| 1552 | /** The tablespace of the table */ |
| 1553 | fil_space_t* space; |
| 1554 | /** Tablespace ID */ |
| 1555 | ulint space_id; |
| 1556 | |
| 1557 | /** Stores information about: |
| 1558 | 1 row format (redundant or compact), |
| 1559 | 2 compressed page size (zip shift size), |
| 1560 | 3 whether using atomic blobs, |
| 1561 | 4 whether the table has been created with the option DATA DIRECTORY. |
| 1562 | Use DICT_TF_GET_COMPACT(), DICT_TF_GET_ZIP_SSIZE(), |
| 1563 | DICT_TF_HAS_ATOMIC_BLOBS() and DICT_TF_HAS_DATA_DIR() to parse this |
| 1564 | flag. */ |
| 1565 | unsigned flags:DICT_TF_BITS; |
| 1566 | |
| 1567 | /** Stores information about: |
| 1568 | 1 whether the table has been created using CREATE TEMPORARY TABLE, |
| 1569 | 2 whether the table has an internally defined DOC ID column, |
| 1570 | 3 whether the table has a FTS index, |
| 1571 | 4 whether DOC ID column need to be added to the FTS index, |
| 1572 | 5 whether the table is being created its own tablespace, |
| 1573 | 6 whether the table has been DISCARDed, |
| 1574 | 7 whether the aux FTS tables names are in hex. |
| 1575 | Use DICT_TF2_FLAG_IS_SET() to parse this flag. */ |
| 1576 | unsigned flags2:DICT_TF2_BITS; |
| 1577 | |
| 1578 | /** TRUE if the table is an intermediate table during copy alter |
| 1579 | operation or a partition/subpartition which is required for copying |
| 1580 | data and skip the undo log for insertion of row in the table. |
| 1581 | This variable will be set and unset during extra(), or during the |
| 1582 | process of altering partitions */ |
| 1583 | unsigned skip_alter_undo:1; |
| 1584 | |
| 1585 | /*!< whether this is in a single-table tablespace and the .ibd |
| 1586 | file is missing or page decryption failed and page is corrupted */ |
| 1587 | unsigned file_unreadable:1; |
| 1588 | |
| 1589 | /** TRUE if the table object has been added to the dictionary cache. */ |
| 1590 | unsigned cached:1; |
| 1591 | |
| 1592 | /** TRUE if the table is to be dropped, but not yet actually dropped |
| 1593 | (could in the background drop list). It is turned on at the beginning |
| 1594 | of row_drop_table_for_mysql() and turned off just before we start to |
| 1595 | update system tables for the drop. It is protected by |
| 1596 | dict_operation_lock. */ |
| 1597 | unsigned to_be_dropped:1; |
| 1598 | |
| 1599 | /** Number of non-virtual columns defined so far. */ |
| 1600 | unsigned n_def:10; |
| 1601 | |
| 1602 | /** Number of non-virtual columns. */ |
| 1603 | unsigned n_cols:10; |
| 1604 | |
| 1605 | /** Number of total columns (inlcude virtual and non-virtual) */ |
| 1606 | unsigned n_t_cols:10; |
| 1607 | |
| 1608 | /** Number of total columns defined so far. */ |
| 1609 | unsigned n_t_def:10; |
| 1610 | |
| 1611 | /** Number of virtual columns defined so far. */ |
| 1612 | unsigned n_v_def:10; |
| 1613 | |
| 1614 | /** Number of virtual columns. */ |
| 1615 | unsigned n_v_cols:10; |
| 1616 | |
| 1617 | /** 1 + the position of autoinc counter field in clustered |
| 1618 | index, or 0 if there is no persistent AUTO_INCREMENT column in |
| 1619 | the table. */ |
| 1620 | unsigned persistent_autoinc:10; |
| 1621 | |
| 1622 | /** TRUE if it's not an InnoDB system table or a table that has no FK |
| 1623 | relationships. */ |
| 1624 | unsigned can_be_evicted:1; |
| 1625 | |
| 1626 | /** TRUE if table is corrupted. */ |
| 1627 | unsigned corrupted:1; |
| 1628 | |
| 1629 | /** TRUE if some indexes should be dropped after ONLINE_INDEX_ABORTED |
| 1630 | or ONLINE_INDEX_ABORTED_DROPPED. */ |
| 1631 | unsigned drop_aborted:1; |
| 1632 | |
| 1633 | /** Array of column descriptions. */ |
| 1634 | dict_col_t* cols; |
| 1635 | |
| 1636 | /** Array of virtual column descriptions. */ |
| 1637 | dict_v_col_t* v_cols; |
| 1638 | |
| 1639 | /** List of stored column descriptions. It is used only for foreign key |
| 1640 | check during create table and copy alter operations. |
| 1641 | During copy alter, s_cols list is filled during create table operation |
| 1642 | and need to preserve till rename table operation. That is the |
| 1643 | reason s_cols is a part of dict_table_t */ |
| 1644 | dict_s_col_list* s_cols; |
| 1645 | |
| 1646 | /** Column names packed in a character string |
| 1647 | "name1\0name2\0...nameN\0". Until the string contains n_cols, it will |
| 1648 | be allocated from a temporary heap. The final string will be allocated |
| 1649 | from table->heap. */ |
| 1650 | const char* col_names; |
| 1651 | |
| 1652 | /** Virtual column names */ |
| 1653 | const char* v_col_names; |
| 1654 | unsigned vers_start:10; |
| 1655 | /*!< System Versioning: row start col index */ |
| 1656 | unsigned vers_end:10; |
| 1657 | /*!< System Versioning: row end col index */ |
| 1658 | bool is_system_db; |
| 1659 | /*!< True if the table belongs to a system |
| 1660 | database (mysql, information_schema or |
| 1661 | performance_schema) */ |
| 1662 | dict_frm_t dict_frm_mismatch; |
| 1663 | /*!< !DICT_FRM_CONSISTENT==0 if data |
| 1664 | dictionary information and |
| 1665 | MySQL FRM information mismatch. */ |
| 1666 | /** Hash chain node. */ |
| 1667 | hash_node_t name_hash; |
| 1668 | |
| 1669 | /** Hash chain node. */ |
| 1670 | hash_node_t id_hash; |
| 1671 | |
| 1672 | /** The FTS_DOC_ID_INDEX, or NULL if no fulltext indexes exist */ |
| 1673 | dict_index_t* fts_doc_id_index; |
| 1674 | |
| 1675 | /** List of indexes of the table. */ |
| 1676 | UT_LIST_BASE_NODE_T(dict_index_t) indexes; |
| 1677 | |
| 1678 | /** List of foreign key constraints in the table. These refer to |
| 1679 | columns in other tables. */ |
| 1680 | UT_LIST_BASE_NODE_T(dict_foreign_t) foreign_list; |
| 1681 | |
| 1682 | /** List of foreign key constraints which refer to this table. */ |
| 1683 | UT_LIST_BASE_NODE_T(dict_foreign_t) referenced_list; |
| 1684 | |
| 1685 | /** Node of the LRU list of tables. */ |
| 1686 | UT_LIST_NODE_T(dict_table_t) table_LRU; |
| 1687 | |
| 1688 | /** Maximum recursive level we support when loading tables chained |
| 1689 | together with FK constraints. If exceeds this level, we will stop |
| 1690 | loading child table into memory along with its parent table. */ |
| 1691 | unsigned fk_max_recusive_level:8; |
| 1692 | |
| 1693 | /** Count of how many foreign key check operations are currently being |
| 1694 | performed on the table. We cannot drop the table while there are |
| 1695 | foreign key checks running on it. */ |
| 1696 | ulint n_foreign_key_checks_running; |
| 1697 | |
| 1698 | /** Transactions whose view low limit is greater than this number are |
| 1699 | not allowed to store to the MySQL query cache or retrieve from it. |
| 1700 | When a trx with undo logs commits, it sets this to the value of the |
| 1701 | current time. */ |
| 1702 | trx_id_t query_cache_inv_id; |
| 1703 | |
| 1704 | /** Transaction id that last touched the table definition. Either when |
| 1705 | loading the definition or CREATE TABLE, or ALTER TABLE (prepare, |
| 1706 | commit, and rollback phases). */ |
| 1707 | trx_id_t def_trx_id; |
| 1708 | |
| 1709 | /*!< set of foreign key constraints in the table; these refer to |
| 1710 | columns in other tables */ |
| 1711 | dict_foreign_set foreign_set; |
| 1712 | |
| 1713 | /*!< set of foreign key constraints which refer to this table */ |
| 1714 | dict_foreign_set referenced_set; |
| 1715 | |
| 1716 | /** Statistics for query optimization. @{ */ |
| 1717 | |
| 1718 | /** Creation state of 'stats_latch'. */ |
| 1719 | volatile os_once::state_t stats_latch_created; |
| 1720 | |
| 1721 | /** This latch protects: |
| 1722 | dict_table_t::stat_initialized, |
| 1723 | dict_table_t::stat_n_rows (*), |
| 1724 | dict_table_t::stat_clustered_index_size, |
| 1725 | dict_table_t::stat_sum_of_other_index_sizes, |
| 1726 | dict_table_t::stat_modified_counter (*), |
| 1727 | dict_table_t::indexes*::stat_n_diff_key_vals[], |
| 1728 | dict_table_t::indexes*::stat_index_size, |
| 1729 | dict_table_t::indexes*::stat_n_leaf_pages. |
| 1730 | (*) Those are not always protected for |
| 1731 | performance reasons. */ |
| 1732 | rw_lock_t* stats_latch; |
| 1733 | |
| 1734 | /** TRUE if statistics have been calculated the first time after |
| 1735 | database startup or table creation. */ |
| 1736 | unsigned stat_initialized:1; |
| 1737 | |
| 1738 | /** Timestamp of last recalc of the stats. */ |
| 1739 | ib_time_t stats_last_recalc; |
| 1740 | |
| 1741 | /** The two bits below are set in the 'stat_persistent' member. They |
| 1742 | have the following meaning: |
| 1743 | 1. _ON=0, _OFF=0, no explicit persistent stats setting for this table, |
| 1744 | the value of the global srv_stats_persistent is used to determine |
| 1745 | whether the table has persistent stats enabled or not |
| 1746 | 2. _ON=0, _OFF=1, persistent stats are explicitly disabled for this |
| 1747 | table, regardless of the value of the global srv_stats_persistent |
| 1748 | 3. _ON=1, _OFF=0, persistent stats are explicitly enabled for this |
| 1749 | table, regardless of the value of the global srv_stats_persistent |
| 1750 | 4. _ON=1, _OFF=1, not allowed, we assert if this ever happens. */ |
| 1751 | #define DICT_STATS_PERSISTENT_ON (1 << 1) |
| 1752 | #define DICT_STATS_PERSISTENT_OFF (1 << 2) |
| 1753 | |
| 1754 | /** Indicates whether the table uses persistent stats or not. See |
| 1755 | DICT_STATS_PERSISTENT_ON and DICT_STATS_PERSISTENT_OFF. */ |
| 1756 | ib_uint32_t stat_persistent; |
| 1757 | |
| 1758 | /** The two bits below are set in the 'stats_auto_recalc' member. They |
| 1759 | have the following meaning: |
| 1760 | 1. _ON=0, _OFF=0, no explicit auto recalc setting for this table, the |
| 1761 | value of the global srv_stats_persistent_auto_recalc is used to |
| 1762 | determine whether the table has auto recalc enabled or not |
| 1763 | 2. _ON=0, _OFF=1, auto recalc is explicitly disabled for this table, |
| 1764 | regardless of the value of the global srv_stats_persistent_auto_recalc |
| 1765 | 3. _ON=1, _OFF=0, auto recalc is explicitly enabled for this table, |
| 1766 | regardless of the value of the global srv_stats_persistent_auto_recalc |
| 1767 | 4. _ON=1, _OFF=1, not allowed, we assert if this ever happens. */ |
| 1768 | #define DICT_STATS_AUTO_RECALC_ON (1 << 1) |
| 1769 | #define DICT_STATS_AUTO_RECALC_OFF (1 << 2) |
| 1770 | |
| 1771 | /** Indicates whether the table uses automatic recalc for persistent |
| 1772 | stats or not. See DICT_STATS_AUTO_RECALC_ON and |
| 1773 | DICT_STATS_AUTO_RECALC_OFF. */ |
| 1774 | ib_uint32_t stats_auto_recalc; |
| 1775 | |
| 1776 | /** The number of pages to sample for this table during persistent |
| 1777 | stats estimation. If this is 0, then the value of the global |
| 1778 | srv_stats_persistent_sample_pages will be used instead. */ |
| 1779 | ulint stats_sample_pages; |
| 1780 | |
| 1781 | /** Approximate number of rows in the table. We periodically calculate |
| 1782 | new estimates. */ |
| 1783 | ib_uint64_t stat_n_rows; |
| 1784 | |
| 1785 | /** Approximate clustered index size in database pages. */ |
| 1786 | ulint stat_clustered_index_size; |
| 1787 | |
| 1788 | /** Approximate size of other indexes in database pages. */ |
| 1789 | ulint stat_sum_of_other_index_sizes; |
| 1790 | |
| 1791 | /** How many rows are modified since last stats recalc. When a row is |
| 1792 | inserted, updated, or deleted, we add 1 to this number; we calculate |
| 1793 | new estimates for the table and the indexes if the table has changed |
| 1794 | too much, see dict_stats_update_if_needed(). The counter is reset |
| 1795 | to zero at statistics calculation. This counter is not protected by |
| 1796 | any latch, because this is only used for heuristics. */ |
| 1797 | ib_uint64_t stat_modified_counter; |
| 1798 | |
| 1799 | /** Background stats thread is not working on this table. */ |
| 1800 | #define BG_STAT_NONE 0 |
| 1801 | |
| 1802 | /** Set in 'stats_bg_flag' when the background stats code is working |
| 1803 | on this table. The DROP TABLE code waits for this to be cleared before |
| 1804 | proceeding. */ |
| 1805 | #define BG_STAT_IN_PROGRESS (1 << 0) |
| 1806 | |
| 1807 | /** Set in 'stats_bg_flag' when DROP TABLE starts waiting on |
| 1808 | BG_STAT_IN_PROGRESS to be cleared. The background stats thread will |
| 1809 | detect this and will eventually quit sooner. */ |
| 1810 | #define BG_STAT_SHOULD_QUIT (1 << 1) |
| 1811 | |
| 1812 | /** The state of the background stats thread wrt this table. |
| 1813 | See BG_STAT_NONE, BG_STAT_IN_PROGRESS and BG_STAT_SHOULD_QUIT. |
| 1814 | Writes are covered by dict_sys->mutex. Dirty reads are possible. */ |
| 1815 | |
| 1816 | #define BG_SCRUB_IN_PROGRESS ((byte)(1 << 2)) |
| 1817 | /*!< BG_SCRUB_IN_PROGRESS is set in |
| 1818 | stats_bg_flag when the background |
| 1819 | scrub code is working on this table. The DROP |
| 1820 | TABLE code waits for this to be cleared |
| 1821 | before proceeding. */ |
| 1822 | |
| 1823 | #define BG_STAT_SHOULD_QUIT (1 << 1) |
| 1824 | |
| 1825 | #define BG_IN_PROGRESS (BG_STAT_IN_PROGRESS | BG_SCRUB_IN_PROGRESS) |
| 1826 | |
| 1827 | |
| 1828 | /** The state of the background stats thread wrt this table. |
| 1829 | See BG_STAT_NONE, BG_STAT_IN_PROGRESS and BG_STAT_SHOULD_QUIT. |
| 1830 | Writes are covered by dict_sys->mutex. Dirty reads are possible. */ |
| 1831 | byte stats_bg_flag; |
| 1832 | |
| 1833 | bool stats_error_printed; |
| 1834 | /*!< Has persistent stats error beein |
| 1835 | already printed for this table ? */ |
| 1836 | /* @} */ |
| 1837 | |
| 1838 | /** AUTOINC related members. @{ */ |
| 1839 | |
| 1840 | /* The actual collection of tables locked during AUTOINC read/write is |
| 1841 | kept in trx_t. In order to quickly determine whether a transaction has |
| 1842 | locked the AUTOINC lock we keep a pointer to the transaction here in |
| 1843 | the 'autoinc_trx' member. This is to avoid acquiring the |
| 1844 | lock_sys_t::mutex and scanning the vector in trx_t. |
| 1845 | When an AUTOINC lock has to wait, the corresponding lock instance is |
| 1846 | created on the trx lock heap rather than use the pre-allocated instance |
| 1847 | in autoinc_lock below. */ |
| 1848 | |
| 1849 | /** A buffer for an AUTOINC lock for this table. We allocate the |
| 1850 | memory here so that individual transactions can get it and release it |
| 1851 | without a need to allocate space from the lock heap of the trx: |
| 1852 | otherwise the lock heap would grow rapidly if we do a large insert |
| 1853 | from a select. */ |
| 1854 | lock_t* autoinc_lock; |
| 1855 | |
| 1856 | /** Creation state of autoinc_mutex member */ |
| 1857 | volatile os_once::state_t autoinc_mutex_created; |
| 1858 | |
| 1859 | /** Mutex protecting the autoincrement counter. */ |
| 1860 | ib_mutex_t* autoinc_mutex; |
| 1861 | |
| 1862 | /** Autoinc counter value to give to the next inserted row. */ |
| 1863 | ib_uint64_t autoinc; |
| 1864 | |
| 1865 | /** This counter is used to track the number of granted and pending |
| 1866 | autoinc locks on this table. This value is set after acquiring the |
| 1867 | lock_sys_t::mutex but we peek the contents to determine whether other |
| 1868 | transactions have acquired the AUTOINC lock or not. Of course only one |
| 1869 | transaction can be granted the lock but there can be multiple |
| 1870 | waiters. */ |
| 1871 | ulong n_waiting_or_granted_auto_inc_locks; |
| 1872 | |
| 1873 | /** The transaction that currently holds the the AUTOINC lock on this |
| 1874 | table. Protected by lock_sys.mutex. */ |
| 1875 | const trx_t* autoinc_trx; |
| 1876 | |
| 1877 | /* @} */ |
| 1878 | |
| 1879 | /** FTS specific state variables. */ |
| 1880 | fts_t* fts; |
| 1881 | |
| 1882 | /** Quiescing states, protected by the dict_index_t::lock. ie. we can |
| 1883 | only change the state if we acquire all the latches (dict_index_t::lock) |
| 1884 | in X mode of this table's indexes. */ |
| 1885 | ib_quiesce_t quiesce; |
| 1886 | |
| 1887 | /** Count of the number of record locks on this table. We use this to |
| 1888 | determine whether we can evict the table from the dictionary cache. |
| 1889 | It is protected by lock_sys.mutex. */ |
| 1890 | ulint n_rec_locks; |
| 1891 | |
| 1892 | #ifndef DBUG_ASSERT_EXISTS |
| 1893 | private: |
| 1894 | #endif |
| 1895 | /** Count of how many handles are opened to this table. Dropping of the |
| 1896 | table is NOT allowed until this count gets to zero. MySQL does NOT |
| 1897 | itself check the number of open handles at DROP. */ |
| 1898 | ulint n_ref_count; |
| 1899 | |
| 1900 | public: |
| 1901 | /** List of locks on the table. Protected by lock_sys.mutex. */ |
| 1902 | table_lock_list_t locks; |
| 1903 | |
| 1904 | /** Timestamp of the last modification of this table. */ |
| 1905 | time_t update_time; |
| 1906 | |
| 1907 | #ifdef UNIV_DEBUG |
| 1908 | /** Value of 'magic_n'. */ |
| 1909 | #define DICT_TABLE_MAGIC_N 76333786 |
| 1910 | |
| 1911 | /** Magic number. */ |
| 1912 | ulint magic_n; |
| 1913 | #endif /* UNIV_DEBUG */ |
| 1914 | /** mysql_row_templ_t for base columns used for compute the virtual |
| 1915 | columns */ |
| 1916 | dict_vcol_templ_t* vc_templ; |
| 1917 | }; |
| 1918 | |
| 1919 | inline void dict_index_t::set_modified(mtr_t& mtr) const |
| 1920 | { |
| 1921 | mtr.set_named_space(table->space); |
| 1922 | } |
| 1923 | |
| 1924 | inline bool dict_index_t::is_readable() const { return table->is_readable(); } |
| 1925 | |
| 1926 | inline bool dict_index_t::is_instant() const |
| 1927 | { |
| 1928 | ut_ad(n_core_fields > 0); |
| 1929 | ut_ad(n_core_fields <= n_fields); |
| 1930 | ut_ad(n_core_fields == n_fields |
| 1931 | || (type & ~(DICT_UNIQUE | DICT_CORRUPT)) == DICT_CLUSTERED); |
| 1932 | ut_ad(n_core_fields == n_fields || table->supports_instant()); |
| 1933 | ut_ad(n_core_fields == n_fields || !table->is_temporary()); |
| 1934 | return(n_core_fields != n_fields); |
| 1935 | } |
| 1936 | |
| 1937 | inline bool dict_index_t::is_corrupted() const |
| 1938 | { |
| 1939 | return UNIV_UNLIKELY(online_status >= ONLINE_INDEX_ABORTED |
| 1940 | || (type & DICT_CORRUPT) |
| 1941 | || (table && table->corrupted)); |
| 1942 | } |
| 1943 | |
| 1944 | /*******************************************************************//** |
| 1945 | Initialise the table lock list. */ |
| 1946 | void |
| 1947 | lock_table_lock_list_init( |
| 1948 | /*======================*/ |
| 1949 | table_lock_list_t* locks); /*!< List to initialise */ |
| 1950 | |
| 1951 | /** A function object to add the foreign key constraint to the referenced set |
| 1952 | of the referenced table, if it exists in the dictionary cache. */ |
| 1953 | struct dict_foreign_add_to_referenced_table { |
| 1954 | void operator()(dict_foreign_t* foreign) const |
| 1955 | { |
| 1956 | if (dict_table_t* table = foreign->referenced_table) { |
| 1957 | std::pair<dict_foreign_set::iterator, bool> ret |
| 1958 | = table->referenced_set.insert(foreign); |
| 1959 | ut_a(ret.second); |
| 1960 | } |
| 1961 | } |
| 1962 | }; |
| 1963 | |
| 1964 | /** Destroy the autoinc latch of the given table. |
| 1965 | This function is only called from either single threaded environment |
| 1966 | or from a thread that has not shared the table object with other threads. |
| 1967 | @param[in,out] table table whose stats latch to destroy */ |
| 1968 | inline |
| 1969 | void |
| 1970 | dict_table_autoinc_destroy( |
| 1971 | dict_table_t* table) |
| 1972 | { |
| 1973 | if (table->autoinc_mutex_created == os_once::DONE |
| 1974 | && table->autoinc_mutex != NULL) { |
| 1975 | mutex_free(table->autoinc_mutex); |
| 1976 | UT_DELETE(table->autoinc_mutex); |
| 1977 | } |
| 1978 | } |
| 1979 | |
| 1980 | /** Request for lazy creation of the autoinc latch of a given table. |
| 1981 | This function is only called from either single threaded environment |
| 1982 | or from a thread that has not shared the table object with other threads. |
| 1983 | @param[in,out] table table whose autoinc latch is to be created. */ |
| 1984 | inline |
| 1985 | void |
| 1986 | dict_table_autoinc_create_lazy( |
| 1987 | dict_table_t* table) |
| 1988 | { |
| 1989 | table->autoinc_mutex = NULL; |
| 1990 | table->autoinc_mutex_created = os_once::NEVER_DONE; |
| 1991 | } |
| 1992 | |
| 1993 | /** Request a lazy creation of dict_index_t::zip_pad::mutex. |
| 1994 | This function is only called from either single threaded environment |
| 1995 | or from a thread that has not shared the table object with other threads. |
| 1996 | @param[in,out] index index whose zip_pad mutex is to be created */ |
| 1997 | inline |
| 1998 | void |
| 1999 | dict_index_zip_pad_mutex_create_lazy( |
| 2000 | dict_index_t* index) |
| 2001 | { |
| 2002 | index->zip_pad.mutex = NULL; |
| 2003 | index->zip_pad.mutex_created = os_once::NEVER_DONE; |
| 2004 | } |
| 2005 | |
| 2006 | /** Destroy the zip_pad_mutex of the given index. |
| 2007 | This function is only called from either single threaded environment |
| 2008 | or from a thread that has not shared the table object with other threads. |
| 2009 | @param[in,out] table table whose stats latch to destroy */ |
| 2010 | inline |
| 2011 | void |
| 2012 | dict_index_zip_pad_mutex_destroy( |
| 2013 | dict_index_t* index) |
| 2014 | { |
| 2015 | if (index->zip_pad.mutex_created == os_once::DONE |
| 2016 | && index->zip_pad.mutex != NULL) { |
| 2017 | mutex_free(index->zip_pad.mutex); |
| 2018 | UT_DELETE(index->zip_pad.mutex); |
| 2019 | } |
| 2020 | } |
| 2021 | |
| 2022 | /** Release the zip_pad_mutex of a given index. |
| 2023 | @param[in,out] index index whose zip_pad_mutex is to be released */ |
| 2024 | inline |
| 2025 | void |
| 2026 | dict_index_zip_pad_unlock( |
| 2027 | dict_index_t* index) |
| 2028 | { |
| 2029 | mutex_exit(index->zip_pad.mutex); |
| 2030 | } |
| 2031 | |
| 2032 | #ifdef UNIV_DEBUG |
| 2033 | /** Check if the current thread owns the autoinc_mutex of a given table. |
| 2034 | @param[in] table the autoinc_mutex belongs to this table |
| 2035 | @return true, if the current thread owns the autoinc_mutex, false otherwise.*/ |
| 2036 | inline |
| 2037 | bool |
| 2038 | dict_table_autoinc_own( |
| 2039 | const dict_table_t* table) |
| 2040 | { |
| 2041 | return(mutex_own(table->autoinc_mutex)); |
| 2042 | } |
| 2043 | #endif /* UNIV_DEBUG */ |
| 2044 | |
| 2045 | /** Check whether the col is used in spatial index or regular index. |
| 2046 | @param[in] col column to check |
| 2047 | @return spatial status */ |
| 2048 | inline |
| 2049 | spatial_status_t |
| 2050 | dict_col_get_spatial_status( |
| 2051 | const dict_col_t* col) |
| 2052 | { |
| 2053 | spatial_status_t spatial_status = SPATIAL_NONE; |
| 2054 | |
| 2055 | /* Column is not a part of any index. */ |
| 2056 | if (!col->ord_part) { |
| 2057 | return(spatial_status); |
| 2058 | } |
| 2059 | |
| 2060 | if (DATA_GEOMETRY_MTYPE(col->mtype)) { |
| 2061 | if (col->max_prefix == 0) { |
| 2062 | spatial_status = SPATIAL_ONLY; |
| 2063 | } else { |
| 2064 | /* Any regular index on a geometry column |
| 2065 | should have a prefix. */ |
| 2066 | spatial_status = SPATIAL_MIXED; |
| 2067 | } |
| 2068 | } |
| 2069 | |
| 2070 | return(spatial_status); |
| 2071 | } |
| 2072 | |
| 2073 | /** Clear defragmentation summary. */ |
| 2074 | inline void dict_stats_empty_defrag_summary(dict_index_t* index) |
| 2075 | { |
| 2076 | index->stat_defrag_n_pages_freed = 0; |
| 2077 | } |
| 2078 | |
| 2079 | /** Clear defragmentation related index stats. */ |
| 2080 | inline void dict_stats_empty_defrag_stats(dict_index_t* index) |
| 2081 | { |
| 2082 | index->stat_defrag_modified_counter = 0; |
| 2083 | index->stat_defrag_n_page_split = 0; |
| 2084 | } |
| 2085 | |
| 2086 | #include "dict0mem.ic" |
| 2087 | |
| 2088 | #endif /* dict0mem_h */ |
| 2089 | |