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 | |