1 /*****************************************************************************
2
3 Copyright (c) 2015, 2020, Oracle and/or its affiliates. All Rights Reserved.
4
5 This program is free software; you can redistribute it and/or modify it under
6 the terms of the GNU General Public License, version 2.0, as published by the
7 Free Software Foundation.
8
9 This program is also distributed with certain software (including but not
10 limited to OpenSSL) that is licensed under separate terms, as designated in a
11 particular file or component or in included license documentation. The authors
12 of MySQL hereby grant you an additional permission to link the program and
13 your derivative works with the separately licensed software that they have
14 included with MySQL.
15
16 This program is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
19 for more details.
20
21 You should have received a copy of the GNU General Public License along with
22 this program; if not, write to the Free Software Foundation, Inc.,
23 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24
25 *****************************************************************************/
26
27 /** @file include/dict0dd.h
28 Data dictionary interface */
29
30 #ifndef dict0dd_h
31 #define dict0dd_h
32
33 #include "dict0dict.h"
34 #include "dict0mem.h"
35 #include "dict0types.h"
36 #include "my_compiler.h"
37 #include "univ.i"
38
39 #ifndef UNIV_HOTBACKUP
40 #include "dd/cache/dictionary_client.h"
41 #include "dd/dd.h"
42 #include "dd/dd_schema.h"
43 #include "dd/dd_table.h"
44 #include "dd/dictionary.h"
45 #include "dd/properties.h"
46 #include "dd/types/column.h"
47 #include "dd/types/column_type_element.h"
48 #include "dd/types/foreign_key.h"
49 #include "dd/types/foreign_key_element.h"
50 #include "dd/types/index.h"
51 #include "dd/types/index_element.h"
52 #include "dd/types/partition.h"
53 #include "dd/types/partition_index.h"
54 #include "dd/types/table.h"
55 #include "dd/types/tablespace.h"
56 #include "dd/types/tablespace_file.h"
57 #include "dd_table_share.h"
58 #include "sess0sess.h"
59 #else
60 #include "mysql_com.h"
61 #endif /* !UNIV_HOTBACKUP */
62 #include "mysql_version.h"
63
64 #ifndef UNIV_HOTBACKUP
65 class THD;
66 class MDL_ticket;
67
68 /** DD functions return false for success and true for failure
69 because that is the way the server functions are defined. */
70 #define DD_SUCCESS false
71 #define DD_FAILURE true
72
73 /** Handler name for InnoDB */
74 static constexpr char handler_name[] = "InnoDB";
75
76 static const char innobase_hton_name[] = "InnoDB";
77
78 /** Maximum hardcoded data dictionary tables. */
79 #define DICT_MAX_DD_TABLES 1024
80
81 /** InnoDB private keys for dd::Table */
82 enum dd_table_keys {
83 /** Auto-increment counter */
84 DD_TABLE_AUTOINC,
85 /** DATA DIRECTORY (static metadata) */
86 DD_TABLE_DATA_DIRECTORY,
87 /** Dynamic metadata version */
88 DD_TABLE_VERSION,
89 /** Discard flag. Please don't use it directly, and instead use
90 dd_is_discarded and dd_set_discarded functions. Discard flag is defined
91 for both dd::Table and dd::Partition and it's easy to confuse.
92 The functions will choose right implementation for you, depending on
93 whether the argument is dd::Table or dd::Partition. */
94 DD_TABLE_DISCARD,
95 /** Columns before first instant ADD COLUMN */
96 DD_TABLE_INSTANT_COLS,
97 /** Sentinel */
98 DD_TABLE__LAST
99 };
100
101 /** InnoDB private keys for dd::Column */
102 /** About the DD_INSTANT_COLUMN_DEFAULT*, please note that if it's a
103 partitioned table, not every default value is needed for every partition.
104 For example, after ALTER TABLE ... PARTITION, maybe some partitions only
105 need part or even none of the default values. Let's say there are two
106 partitions, p1 and p2. p1 needs 10 default values while p2 needs 2.
107 If another ALTER ... PARTITION makes p1 a fresh new partition which
108 doesn't need the default values any more, currently, the extra 8(10 - 2)
109 default values are not removed form dd::Column::se_private_data. */
110 enum dd_column_keys {
111 /** Default value when it was added instantly */
112 DD_INSTANT_COLUMN_DEFAULT,
113 /** Default value is null or not */
114 DD_INSTANT_COLUMN_DEFAULT_NULL,
115 /** Sentinel */
116 DD_COLUMN__LAST
117 };
118
119 #endif /* !UNIV_HOTBACKUP */
120
121 /** Server version that the tablespace created */
122 const uint32 DD_SPACE_CURRENT_SRV_VERSION = MYSQL_VERSION_ID;
123
124 /** The tablespace version that the tablespace created */
125 const uint32 DD_SPACE_CURRENT_SPACE_VERSION = 1;
126
127 #ifndef UNIV_HOTBACKUP
128 /** InnoDB private keys for dd::Partition */
129 enum dd_partition_keys {
130 /** Row format for this partition */
131 DD_PARTITION_ROW_FORMAT,
132 /** Columns before first instant ADD COLUMN.
133 This is necessary for each partition because differnet partition
134 may have different instant column numbers, especially, for a
135 newly truncated partition, it can have no instant columns.
136 So partition level one should be always >= table level one. */
137 DD_PARTITION_INSTANT_COLS,
138 /** Discard flag. Please don't use it directly, and instead use
139 dd_is_discarded and dd_set_discarded functions. Discard flag is defined
140 for both dd::Table and dd::Partition and it's easy to confuse.
141 The functions will choose right implementation for you, depending on
142 whether the argument is dd::Table or dd::Partition. */
143 DD_PARTITION_DISCARD,
144 /** Sentinel */
145 DD_PARTITION__LAST
146 };
147
148 /** InnoDB private keys for dd::Tablespace */
149 enum dd_space_keys {
150 /** Tablespace flags */
151 DD_SPACE_FLAGS,
152 /** Tablespace identifier */
153 DD_SPACE_ID,
154 /** Discard attribute */
155 DD_SPACE_DISCARD,
156 /** Server version */
157 DD_SPACE_SERVER_VERSION,
158 /** TABLESPACE_VERSION */
159 DD_SPACE_VERSION,
160 /** Current state attribute */
161 DD_SPACE_STATE,
162 /** Sentinel */
163 DD_SPACE__LAST
164 };
165
166 /** Values for InnoDB private key "state" for dd::Tablespace */
167 enum dd_space_states {
168 /** Normal IBD tablespace */
169 DD_SPACE_STATE_NORMAL,
170 /** Discarded IBD tablespace */
171 DD_SPACE_STATE_DISCARDED,
172 /** Corrupted IBD tablespace */
173 DD_SPACE_STATE_CORRUPTED,
174 /** Active undo tablespace */
175 DD_SPACE_STATE_ACTIVE,
176 /** Inactive undo tablespace being truncated, selected
177 explicitly by ALTER UNDO TABLESPACE SET INACTIVE.
178 Note: the DD is not updated when an undo space is selected
179 for truncation implicitly by the purge thread. */
180 DD_SPACE_STATE_INACTIVE,
181 /** Inactive undo tablespace being truncated, selected
182 explicitly by ALTER UNDO TABLESPACE SET INACTIVE. */
183 DD_SPACE_STATE_EMPTY,
184 /** Sentinel */
185 DD_SPACE_STATE__LAST
186 };
187
188 /** InnoDB implicit tablespace name or prefix, which should be same to
189 dict_sys_t::s_file_per_table_name */
190 static constexpr char reserved_implicit_name[] = "innodb_file_per_table";
191
192 /** InnoDB private key strings for dd::Tablespace.
193 @see dd_space_keys */
194 const char *const dd_space_key_strings[DD_SPACE__LAST] = {
195 "flags", "id", "discard", "server_version", "space_version", "state"};
196
197 /** InnoDB private value strings for key string "state" in dd::Tablespace.
198 @see dd_space_state_values */
199 const char *const dd_space_state_values[DD_SPACE_STATE__LAST + 1] = {
200 "normal", /* for IBD spaces */
201 "discarded", /* for IBD spaces */
202 "corrupted", /* for IBD spaces */
203 "active", /* for undo spaces*/
204 "inactive", /* for undo spaces */
205 "empty", /* for undo spaces */
206 "unknown" /* for non-existing or unknown spaces */
207 };
208
209 /** InnoDB private key strings for dd::Table. @see dd_table_keys */
210 const char *const dd_table_key_strings[DD_TABLE__LAST] = {
211 "autoinc", "data_directory", "version", "discard", "instant_col"};
212
213 /** InnoDB private key strings for dd::Column, @see dd_column_keys */
214 const char *const dd_column_key_strings[DD_COLUMN__LAST] = {"default",
215 "default_null"};
216
217 /** InnoDB private key strings for dd::Partition. @see dd_partition_keys */
218 const char *const dd_partition_key_strings[DD_PARTITION__LAST] = {
219 "format", "instant_col", "discard"};
220
221 /** InnoDB private keys for dd::Index or dd::Partition_index */
222 enum dd_index_keys {
223 /** Index identifier */
224 DD_INDEX_ID,
225 /** Space id */
226 DD_INDEX_SPACE_ID,
227 /** Table id */
228 DD_TABLE_ID,
229 /** Root page number */
230 DD_INDEX_ROOT,
231 /** Creating transaction ID */
232 DD_INDEX_TRX_ID,
233 /** Sentinel */
234 DD_INDEX__LAST
235 };
236
237 /** InnoDB private key strings for dd::Index or dd::Partition_index.
238 @see dd_index_keys */
239 const char *const dd_index_key_strings[DD_INDEX__LAST] = {
240 "id", "space_id", "table_id", "root", "trx_id"};
241
242 /** InnoDB private key strings for dd::Index or dd::Partition_index.
243 @see dd_index_keys */
244 extern const char *const dd_index_key_strings[DD_INDEX__LAST];
245
246 /** dd::Partition::options() key for INDEX DIRECTORY */
247 static const dd::String_type index_file_name_key("index_file_name");
248 /** dd::Partition::options() key for DATA DIRECTORY */
249 static const dd::String_type data_file_name_key("data_file_name");
250
251 /** Table names needed to process I_S queries. */
252 static const dd::String_type dd_tables_name("mysql/tables");
253 static const dd::String_type dd_partitions_name("mysql/table_partitions");
254 static const dd::String_type dd_tablespaces_name("mysql/tablespaces");
255 static const dd::String_type dd_indexes_name("mysql/indexes");
256 static const dd::String_type dd_columns_name("mysql/columns");
257
258 #ifdef UNIV_DEBUG
259
260 /** Hard-coded data dictionary information */
261 struct innodb_dd_table_t {
262 /** Data dictionary table name */
263 const char *name;
264 /** Number of indexes */
265 const uint n_indexes;
266 };
267
268 /** The hard-coded data dictionary tables. */
269 const innodb_dd_table_t innodb_dd_table[] = {
270 INNODB_DD_TABLE("dd_properties", 1),
271
272 INNODB_DD_TABLE("innodb_dynamic_metadata", 1),
273 INNODB_DD_TABLE("innodb_table_stats", 1),
274 INNODB_DD_TABLE("innodb_index_stats", 1),
275 INNODB_DD_TABLE("innodb_ddl_log", 2),
276
277 INNODB_DD_TABLE("catalogs", 2),
278 INNODB_DD_TABLE("character_sets", 3),
279 INNODB_DD_TABLE("check_constraints", 3),
280 INNODB_DD_TABLE("collations", 3),
281 INNODB_DD_TABLE("column_statistics", 3),
282 INNODB_DD_TABLE("column_type_elements", 1),
283 INNODB_DD_TABLE("columns", 5),
284 INNODB_DD_TABLE("events", 5),
285 INNODB_DD_TABLE("foreign_key_column_usage", 3),
286 INNODB_DD_TABLE("foreign_keys", 4),
287 INNODB_DD_TABLE("index_column_usage", 3),
288 INNODB_DD_TABLE("index_partitions", 3),
289 INNODB_DD_TABLE("index_stats", 1),
290 INNODB_DD_TABLE("indexes", 3),
291 INNODB_DD_TABLE("parameter_type_elements", 1),
292 INNODB_DD_TABLE("parameters", 3),
293 INNODB_DD_TABLE("resource_groups", 2),
294 INNODB_DD_TABLE("routines", 6),
295 INNODB_DD_TABLE("schemata", 3),
296 INNODB_DD_TABLE("st_spatial_reference_systems", 3),
297 INNODB_DD_TABLE("table_partition_values", 1),
298 INNODB_DD_TABLE("table_partitions", 7),
299 INNODB_DD_TABLE("table_stats", 1),
300 INNODB_DD_TABLE("tables", 9),
301 INNODB_DD_TABLE("tablespace_files", 2),
302 INNODB_DD_TABLE("tablespaces", 2),
303 INNODB_DD_TABLE("triggers", 6),
304 INNODB_DD_TABLE("view_routine_usage", 2),
305 INNODB_DD_TABLE("view_table_usage", 2)};
306
307 /** Number of hard-coded data dictionary tables */
308 static constexpr size_t innodb_dd_table_size = UT_ARR_SIZE(innodb_dd_table);
309
310 /** @return total number of indexes of all DD Tables. */
311 uint32_t dd_get_total_indexes_num();
312
313 #endif /* UNIV_DEBUG */
314
315 #endif /* !UNIV_HOTBACKUP */
316
317 /** Class to decode or encode a stream of default value for instant table.
318 The decode/encode are necessary because that the default values would b
319 kept as InnoDB format stream, which is in fact byte stream. However,
320 to store them in the DD se_private_data, it requires text(char).
321 So basically, the encode will change the byte stream into char stream,
322 by spliting every byte into two chars, for example, 0xFF, would be splitted
323 into 0x0F and 0x0F. So the final storage space would be double. For the
324 decode, it's the converse process, combining two chars into one byte. */
325 class DD_instant_col_val_coder {
326 public:
327 /** Constructor */
DD_instant_col_val_coder()328 DD_instant_col_val_coder() : m_result(nullptr) {}
329
330 /** Destructor */
~DD_instant_col_val_coder()331 ~DD_instant_col_val_coder() { cleanup(); }
332
333 /** Encode the specified stream in format of bytes into chars
334 @param[in] stream stream to encode in bytes
335 @param[in] in_len length of the stream
336 @param[out] out_len length of the encoded stream
337 @return the encoded stream, which would be destroyed if the class
338 itself is destroyed */
339 const char *encode(const byte *stream, size_t in_len, size_t *out_len);
340
341 /** Decode the specified stream, which is encoded by encode()
342 @param[in] stream stream to decode in chars
343 @param[in] in_len length of the stream
344 @param[out] out_len length of the decoded stream
345 @return the decoded stream, which would be destroyed if the class
346 itself is destroyed */
347 const byte *decode(const char *stream, size_t in_len, size_t *out_len);
348
349 private:
350 /** Clean-up last result */
cleanup()351 void cleanup() { UT_DELETE_ARRAY(m_result); }
352
353 private:
354 /** The encoded or decoded stream */
355 byte *m_result;
356 };
357
358 #ifndef UNIV_HOTBACKUP
359 /** Determine if a dd::Partition is the first leaf partition in the table
360 @param[in] dd_part dd::Partition
361 @return True If it's the first partition
362 @retval False Not the first one */
dd_part_is_first(const dd::Partition * dd_part)363 inline bool dd_part_is_first(const dd::Partition *dd_part) {
364 return (dd_part == *(dd_part->table().leaf_partitions().begin()));
365 }
366
367 /** Determine if a dd::Table is partitioned table
368 @param[in] table dd::Table
369 @return True If partitioned table
370 @retval False non-partitioned table */
dd_table_is_partitioned(const dd::Table & table)371 inline bool dd_table_is_partitioned(const dd::Table &table) {
372 return (table.partition_type() != dd::Table::PT_NONE);
373 }
374
375 #ifdef UNIV_DEBUG
376 /** Check if the instant columns are consistent with the se_private_data
377 in dd::Table
378 @param[in] dd_table dd::Table
379 @return true if consistent, otherwise false */
380 bool dd_instant_columns_exist(const dd::Table &dd_table);
381 #endif /* UNIV_DEBUG */
382
383 /** Determine if a dd::Table has any instant column
384 @param[in] table dd::Table
385 @return true If it's a table with instant columns
386 @retval false Not a table with instant columns */
dd_table_has_instant_cols(const dd::Table & table)387 inline bool dd_table_has_instant_cols(const dd::Table &table) {
388 bool instant = table.se_private_data().exists(
389 dd_table_key_strings[DD_TABLE_INSTANT_COLS]);
390
391 ut_ad(!instant || dd_instant_columns_exist(table));
392
393 return (instant);
394 }
395
396 /** Determine if a dd::Partition has any instant column
397 @param[in] part dd::Partition
398 @return true If it's a partitioned table with instant columns
399 @return false Not a partitioned table with instant columns */
dd_part_has_instant_cols(const dd::Partition & part)400 inline bool dd_part_has_instant_cols(const dd::Partition &part) {
401 bool instant = part.se_private_data().exists(
402 dd_partition_key_strings[DD_PARTITION_INSTANT_COLS]);
403 ut_ad(!instant || dd_table_has_instant_cols(part.table()));
404
405 return (instant);
406 }
407
408 /** Determine if any partition of the table still has instant columns
409 @param[in] table dd::Table of the partitioned table
410 @return true If any partition still has instant columns
411 @return false No one has instant columns */
dd_table_part_has_instant_cols(const dd::Table & table)412 inline bool dd_table_part_has_instant_cols(const dd::Table &table) {
413 ut_ad(dd_table_is_partitioned(table));
414
415 if (!dd_table_has_instant_cols(table)) {
416 return (false);
417 }
418
419 for (auto part : table.leaf_partitions()) {
420 if (dd_part_has_instant_cols(*part)) {
421 return (true);
422 }
423 }
424 return (false);
425 }
426
427 /** Determine if dd::Table is discarded. Please note that
428 in case of partitioned Table, only it's leaf partitions can be marked
429 as discarded. However, it's fine to call this function on partitioned
430 Table - it will just return false
431
432 @param[in] table non-partitioned dd::Table
433 @return true if table is marked as discarded
434 @return false if table is not marked as discarded */
dd_is_discarded(const dd::Table & table)435 inline bool dd_is_discarded(const dd::Table &table) {
436 const dd::Properties &table_private = table.se_private_data();
437 bool is_discarded = false;
438 if (table_private.exists(dd_table_key_strings[DD_TABLE_DISCARD])) {
439 table_private.get(dd_table_key_strings[DD_TABLE_DISCARD], &is_discarded);
440 }
441
442 /* In case of partitioned tables, only partitions/subpartitions can ever
443 be marked as discarded */
444 ut_ad(!is_discarded || !dd_table_is_partitioned(table));
445
446 return is_discarded;
447 }
448
449 /** Determine if dd::Partition is discarded. Please note that
450 only leaf partitions can be marked as discarded (that is, if partition has
451 subpartitions, then only subpartitions can be marked as discarded)
452
453 Function can be safely called on a partition, even if it has subpartitions -
454 it will just return false.
455
456 @param[in] partition dd::Partition
457 @return true if partition is marked as discarded
458 @return false if partition is not marked as discarded */
dd_is_discarded(const dd::Partition & partition)459 inline bool dd_is_discarded(const dd::Partition &partition) {
460 const dd::Properties &partition_private = partition.se_private_data();
461 bool is_discarded = false;
462 if (partition_private.exists(
463 dd_partition_key_strings[DD_PARTITION_DISCARD])) {
464 partition_private.get(dd_partition_key_strings[DD_PARTITION_DISCARD],
465 &is_discarded);
466 }
467
468 return is_discarded;
469 }
470
471 /** Sets appropriate discard attribute of dd::Table
472 Please note that this function must not be called on partitioned tables
473
474 @param[in] table non-partitioned dd::Table
475 @param[in] discarded true if Table is discarded, false otherwise */
dd_set_discarded(dd::Table & table,bool discarded)476 inline void dd_set_discarded(dd::Table &table, bool discarded) {
477 ut_ad(!dd_table_is_partitioned(table));
478
479 dd::Properties &p = table.se_private_data();
480 p.set(dd_table_key_strings[DD_TABLE_DISCARD], discarded);
481 }
482
483 /** Sets appropriate discard attribute of dd::Partition
484
485 Please note that this function can be only called on leaf_partitions.
486
487 @param[in] partition leaf dd::Partition
488 @param[in] discarded true if Table is discarded, false otherwise */
dd_set_discarded(dd::Partition & partition,bool discarded)489 inline void dd_set_discarded(dd::Partition &partition, bool discarded) {
490 #ifdef UNIV_DEBUG
491 bool is_leaf = false;
492 for (const dd::Partition *part : *partition.table().leaf_partitions()) {
493 if (part == &partition) {
494 is_leaf = true;
495 break;
496 }
497 }
498 ut_ad(is_leaf);
499 #endif
500
501 dd::Properties &p = partition.se_private_data();
502 p.set(dd_partition_key_strings[DD_PARTITION_DISCARD], discarded);
503 }
504
505 /** Get the first index of a table or partition.
506 @tparam Table dd::Table or dd::Partition
507 @tparam Index dd::Index or dd::Partition_index
508 @param[in] table table containing user columns and indexes
509 @return the first index
510 @retval NULL if there are no indexes */
511 template <typename Table, typename Index>
dd_first(const Table * table)512 inline const Index *dd_first(const Table *table) {
513 return (*table->indexes().begin());
514 }
515
516 /** Get the first index of a table.
517 @param[in] table table containing user columns and indexes
518 @return the first index
519 @retval NULL if there are no indexes */
dd_first_index(const dd::Table * table)520 inline const dd::Index *dd_first_index(const dd::Table *table) {
521 return (dd_first<dd::Table, dd::Index>(table));
522 }
523
524 /** Get the first index of a partition.
525 @param[in] partition partition or subpartition
526 @return the first index
527 @retval NULL if there are no indexes */
dd_first_index(const dd::Partition * partition)528 inline const dd::Partition_index *dd_first_index(
529 const dd::Partition *partition) {
530 return (dd_first<dd::Partition, dd::Partition_index>(partition));
531 }
532
533 #ifdef UNIV_DEBUG
534 /** Determine if a partition is materialized.
535 @param[in] part partition
536 @return whether the partition is materialized */
dd_part_is_stored(const dd::Partition * part)537 inline bool dd_part_is_stored(const dd::Partition *part) {
538 return (part->table().subpartition_type() == dd::Table::ST_NONE ||
539 part->parent());
540 }
541 #endif /* UNIV_DEBUG */
542
543 /** Get the explicit dd::Tablespace::id of a table.
544 @param[in] table non-partitioned table
545 @return the explicit dd::Tablespace::id
546 @retval dd::INVALID_OBJECT_ID if there is no explicit tablespace */
dd_get_space_id(const dd::Table & table)547 inline dd::Object_id dd_get_space_id(const dd::Table &table) {
548 ut_ad(!dd_table_is_partitioned(table));
549 return (table.tablespace_id());
550 }
551
552 /** Get the explicit dd::Tablespace::id of a partition.
553 @param[in] partition partition or subpartition
554 @return the explicit dd::Tablespace::id
555 @retval dd::INVALID_OBJECT_ID if there is no explicit tablespace */
556 inline dd::Object_id dd_get_space_id(const dd::Partition &partition);
557
558 /** Set the AUTO_INCREMENT attribute.
559 @param[in,out] se_private_data dd::Table::se_private_data
560 @param[in] autoinc the auto-increment value */
561 void dd_set_autoinc(dd::Properties &se_private_data, uint64 autoinc);
562
563 /** Get the version attribute.
564 @param[in] dd_table dd::Table
565 @return table dynamic metadata version if exists, otherwise 0 */
566 inline uint64_t dd_get_version(const dd::Table *dd_table);
567
568 /** Copy the AUTO_INCREMENT and version attribute if exist.
569 @param[in] src dd::Table::se_private_data to copy from
570 @param[out] dest dd::Table::se_private_data to copy to */
571 void dd_copy_autoinc(const dd::Properties &src, dd::Properties &dest);
572
573 /** Copy the metadata of a table definition if there was an instant
574 ADD COLUMN happened. This should be done when it's not an ALTER TABLE
575 with rebuild.
576 @param[in,out] new_table New table definition
577 @param[in] old_table Old table definition */
578 void dd_copy_instant_n_cols(dd::Table &new_table, const dd::Table &old_table);
579
580 /** Copy the engine-private parts of a table or partition definition
581 when the change does not affect InnoDB. This mainly copies the common
582 private data between dd::Table and dd::Partition
583 @tparam Table dd::Table or dd::Partition
584 @param[in,out] new_table Copy of old table or partition definition
585 @param[in] old_table Old table or partition definition */
586 template <typename Table>
587 void dd_copy_private(Table &new_table, const Table &old_table);
588
589 /** Copy the engine-private parts of column definitions of a table
590 @param[in,out] new_table Copy of old table
591 @param[in] old_table Old table */
592 void dd_copy_table_columns(dd::Table &new_table, const dd::Table &old_table);
593
594 /** Copy the metadata of a table definition, including the INSTANT
595 ADD COLUMN information. This should be done when it's not an ALTER TABLE
596 with rebuild. Basically, check dd::Table::se_private_data and
597 dd::Column::se_private_data.
598 @param[in,out] new_table Copy of old table definition
599 @param[in] old_table Old table definition */
dd_copy_table(dd::Table & new_table,const dd::Table & old_table)600 inline void dd_copy_table(dd::Table &new_table, const dd::Table &old_table) {
601 /* Copy columns first, to make checking in dd_copy_instant_n_cols pass */
602 dd_copy_table_columns(new_table, old_table);
603 if (dd_table_has_instant_cols(old_table)) {
604 dd_copy_instant_n_cols(new_table, old_table);
605 }
606 }
607
608 /** Adjust TABLE_ID for partitioned table after ALTER TABLE ... PARTITION.
609 This makes sure that the TABLE_ID stored in dd::Column::se_private_data
610 is correct if the first partition got changed
611 @param[in,out] new_table New dd::Table */
612 void dd_part_adjust_table_id(dd::Table *new_table);
613
614 /** Add column default values for new instantly added columns
615 @param[in] old_table MySQL table as it is before the ALTER operation
616 @param[in] altered_table MySQL table that is being altered
617 @param[in,out] new_dd_table New dd::Table
618 @param[in] new_table New InnoDB table object */
619 void dd_add_instant_columns(const TABLE *old_table, const TABLE *altered_table,
620 dd::Table *new_dd_table,
621 const dict_table_t *new_table);
622
623 /** Clear the instant ADD COLUMN information of a table
624 @param[in,out] dd_table dd::Table */
625 void dd_clear_instant_table(dd::Table &dd_table);
626
627 /** Clear the instant ADD COLUMN information of a partition, to make it
628 as a normal partition
629 @param[in,out] dd_part dd::Partition */
630 void dd_clear_instant_part(dd::Partition &dd_part);
631
632 /** Compare the default values between imported column and column defined
633 in the server. Note that it's absolutely OK if there is no default value
634 in the column defined in server, since it can be filled in later.
635 @param[in] dd_col dd::Column
636 @param[in] col InnoDB column object
637 @return true The default values match
638 @retval false Not match */
639 bool dd_match_default_value(const dd::Column *dd_col, const dict_col_t *col);
640
641 /** Write default value of a column to dd::Column
642 @param[in] col default value of this column to write
643 @param[in,out] dd_col where to store the default value */
644 void dd_write_default_value(const dict_col_t *col, dd::Column *dd_col);
645
646 /** Import all metadata which is related to instant ADD COLUMN of a table
647 to dd::Table. This is used for IMPORT.
648 @param[in] table InnoDB table object
649 @param[in,out] dd_table dd::Table */
650 void dd_import_instant_add_columns(const dict_table_t *table,
651 dd::Table *dd_table);
652
653 /** Write metadata of a table to dd::Table
654 @tparam Table dd::Table or dd::Partition
655 @param[in] dd_space_id Tablespace id, which server allocates
656 @param[in,out] dd_table dd::Table or dd::Partition
657 @param[in] table InnoDB table object */
658 template <typename Table>
659 void dd_write_table(dd::Object_id dd_space_id, Table *dd_table,
660 const dict_table_t *table);
661
662 /** Set options of dd::Table according to InnoDB table object
663 @tparam Table dd::Table or dd::Partition
664 @param[in,out] dd_table dd::Table or dd::Partition
665 @param[in] table InnoDB table object */
666 template <typename Table>
667 void dd_set_table_options(Table *dd_table, const dict_table_t *table);
668
669 /** Update virtual columns with new se_private_data, currently, only
670 table_id is set
671 @param[in,out] dd_table dd::Table
672 @param[in] id InnoDB table ID to set */
673 void dd_update_v_cols(dd::Table *dd_table, table_id_t id);
674
675 /** Write metadata of a tablespace to dd::Tablespace
676 @param[in,out] dd_space dd::Tablespace
677 @param[in] space_id InnoDB tablespace ID
678 @param[in] fsp_flags InnoDB tablespace flags
679 @param[in] state InnoDB tablespace state */
680 void dd_write_tablespace(dd::Tablespace *dd_space, space_id_t space_id,
681 uint32_t fsp_flags, dd_space_states state);
682
683 /** Add fts doc id column and index to new table
684 when old table has hidden fts doc id without fulltext index
685 @param[in,out] new_table New dd table
686 @param[in] old_table Old dd table */
687 void dd_add_fts_doc_id_index(dd::Table &new_table, const dd::Table &old_table);
688
689 MY_COMPILER_DIAGNOSTIC_PUSH()
690 MY_COMPILER_CLANG_WORKAROUND_TPARAM_DOCBUG()
691 /** Find the specified dd::Index or dd::Partition_index in an InnoDB table
692 @tparam Index dd::Index or dd::Partition_index
693 @param[in] table InnoDB table object
694 @param[in] dd_index Index to search
695 @return the dict_index_t object related to the index */
696 template <typename Index>
697 const dict_index_t *dd_find_index(const dict_table_t *table, Index *dd_index);
698 MY_COMPILER_DIAGNOSTIC_POP()
699
700 /** Acquire a shared metadata lock.
701 @param[in,out] thd current thread
702 @param[out] mdl metadata lock
703 @param[in] db schema name
704 @param[in] table table name
705 @retval false if acquired, or trylock timed out
706 @retval true if failed (my_error() will have been called) */
707 UNIV_INLINE MY_ATTRIBUTE((warn_unused_result)) bool dd_mdl_acquire(
708 THD *thd, MDL_ticket **mdl, const char *db, const char *table);
709
710 /** Release a metadata lock.
711 @param[in,out] thd current thread
712 @param[in,out] mdl metadata lock */
713 void dd_mdl_release(THD *thd, MDL_ticket **mdl);
714
715 /** Returns thd associated with the trx or current_thd
716 @param[in] trx transaction
717 @return trx->mysql_thd or current_thd */
718 THD *dd_thd_for_undo(const trx_t *trx);
719
720 /** Check if current undo needs a MDL or not
721 @param[in] trx transaction
722 @return true if MDL is necessary, otherwise false */
723 bool dd_mdl_for_undo(const trx_t *trx);
724
725 /** Load foreign key constraint info for the dd::Table object.
726 @param[out] m_table InnoDB table handle
727 @param[in] dd_table Global DD table
728 @param[in] col_names column names, or NULL
729 @param[in] ignore_err DICT_ERR_IGNORE_FK_NOKEY or DICT_ERR_IGNORE_NONE
730 @param[in] dict_locked True if dict_sys->mutex is already held,
731 otherwise false
732 @return DB_SUCESS if successfully load FK constraint */
733 dberr_t dd_table_load_fk_from_dd(dict_table_t *m_table,
734 const dd::Table *dd_table,
735 const char **col_names,
736 dict_err_ignore_t ignore_err,
737 bool dict_locked);
738
739 /** Set the AUTO_INCREMENT attribute.
740 @param[in,out] se_private_data dd::Table::se_private_data
741 @param[in] autoinc the auto-increment value */
742 void dd_set_autoinc(dd::Properties &se_private_data, uint64 autoinc);
743
744 /** Scan a new dd system table, like mysql.tables...
745 @param[in] thd thd
746 @param[in,out] mdl mdl lock
747 @param[in,out] pcur persistent cursor
748 @param[in] mtr the mini-transaction
749 @param[in] system_table_name which dd system table to open
750 @param[in,out] table dict_table_t obj of dd system table
751 @retval the first rec of the dd system table */
752 const rec_t *dd_startscan_system(THD *thd, MDL_ticket **mdl, btr_pcur_t *pcur,
753 mtr_t *mtr, const char *system_table_name,
754 dict_table_t **table);
755
756 /** Process one mysql.tables record and get the dict_table_t
757 @param[in] heap temp memory heap
758 @param[in,out] rec mysql.tables record
759 @param[in,out] table dict_table_t to fill
760 @param[in] dd_tables dict_table_t obj of dd system table
761 @param[in] mdl mdl on the table
762 @param[in] mtr the mini-transaction
763 @retval error message, or NULL on success */
764 const char *dd_process_dd_tables_rec_and_mtr_commit(
765 mem_heap_t *heap, const rec_t *rec, dict_table_t **table,
766 dict_table_t *dd_tables, MDL_ticket **mdl, mtr_t *mtr);
767 /** Process one mysql.table_partitions record and get the dict_table_t
768 @param[in] heap temp memory heap
769 @param[in,out] rec mysql.table_partitions record
770 @param[in,out] table dict_table_t to fill
771 @param[in] dd_tables dict_table_t obj of dd partition table
772 @param[in] mdl mdl on the table
773 @param[in] mtr the mini-transaction
774 @retval error message, or NULL on success */
775 const char *dd_process_dd_partitions_rec_and_mtr_commit(
776 mem_heap_t *heap, const rec_t *rec, dict_table_t **table,
777 dict_table_t *dd_tables, MDL_ticket **mdl, mtr_t *mtr);
778 /** Process one mysql.columns record and get info to dict_col_t
779 @param[in,out] heap temp memory heap
780 @param[in] rec mysql.columns record
781 @param[in,out] col dict_col_t to fill
782 @param[in,out] table_id table id
783 @param[in,out] col_name column name
784 @param[in,out] nth_v_col nth v column
785 @param[in] dd_columns dict_table_t obj of mysql.columns
786 @param[in,out] mtr the mini-transaction
787 @retval true if index is filled */
788 bool dd_process_dd_columns_rec(mem_heap_t *heap, const rec_t *rec,
789 dict_col_t *col, table_id_t *table_id,
790 char **col_name, ulint *nth_v_col,
791 const dict_table_t *dd_columns, mtr_t *mtr);
792
793 /** Process one mysql.columns record for virtual columns
794 @param[in] heap temp memory heap
795 @param[in,out] rec mysql.columns record
796 @param[in,out] table_id table id
797 @param[in,out] pos position
798 @param[in,out] base_pos base column position
799 @param[in,out] n_row number of rows
800 @param[in] dd_columns dict_table_t obj of mysql.columns
801 @param[in] mtr the mini-transaction
802 @retval true if virtual info is filled */
803 bool dd_process_dd_virtual_columns_rec(mem_heap_t *heap, const rec_t *rec,
804 table_id_t *table_id, ulint **pos,
805 ulint **base_pos, ulint *n_row,
806 dict_table_t *dd_columns, mtr_t *mtr);
807
808 /** Get next record of new DD system tables
809 @param[in,out] pcur persistent cursor
810 @param[in] mtr the mini-transaction
811 @retval next record */
812 const rec_t *dd_getnext_system_rec(btr_pcur_t *pcur, mtr_t *mtr);
813
814 /** Process one mysql.indexes record and get the dict_index_t
815 @param[in] heap temp memory heap
816 @param[in,out] rec mysql.indexes record
817 @param[in,out] index dict_index_t to fill
818 @param[in] mdl mdl on index->table
819 @param[in,out] parent parent table if it's fts aux table.
820 @param[in,out] parent_mdl mdl on parent if it's fts aux table.
821 @param[in] dd_indexes dict_table_t obj of mysql.indexes
822 @param[in] mtr the mini-transaction
823 @retval true if index is filled */
824 bool dd_process_dd_indexes_rec(mem_heap_t *heap, const rec_t *rec,
825 const dict_index_t **index, MDL_ticket **mdl,
826 dict_table_t **parent, MDL_ticket **parent_mdl,
827 dict_table_t *dd_indexes, mtr_t *mtr);
828 /** Process one mysql.indexes record and get brief info to dict_index_t
829 @param[in] heap temp memory heap
830 @param[in,out] rec mysql.indexes record
831 @param[in,out] index_id index id
832 @param[in,out] space_id space id
833 @param[in] dd_indexes dict_table_t obj of mysql.indexes
834 @retval true if index is filled */
835 bool dd_process_dd_indexes_rec_simple(mem_heap_t *heap, const rec_t *rec,
836 space_index_t *index_id,
837 space_id_t *space_id,
838 dict_table_t *dd_indexes);
839
840 /** Process one mysql.tablespaces record and get info
841 @param[in] heap temp memory heap
842 @param[in,out] rec mysql.tablespaces record
843 @param[in,out] space_id space id
844 @param[in,out] name space name
845 @param[in,out] flags space flags
846 @param[in,out] server_version server version
847 @param[in,out] space_version space version
848 @param[in,out] is_encrypted true if tablespace is encrypted
849 @param[in,out] state space state
850 @param[in] dd_spaces dict_table_t obj of mysql.tablespaces
851 @return true if data is retrived */
852 bool dd_process_dd_tablespaces_rec(mem_heap_t *heap, const rec_t *rec,
853 space_id_t *space_id, char **name,
854 uint32_t *flags, uint32 *server_version,
855 uint32 *space_version, bool *is_encrypted,
856 dd::String_type *state,
857 dict_table_t *dd_spaces);
858
859 /** Make sure the data_dir_path is saved in dict_table_t if DATA DIRECTORY
860 was used. Try to read it from the fil_system first, then from new dd.
861 @tparam Table dd::Table or dd::Partition
862 @param[in,out] table Table object
863 @param[in] dd_table DD table object
864 @param[in] dict_mutex_own true if dict_sys->mutex is owned already */
865 template <typename Table>
866 void dd_get_and_save_data_dir_path(dict_table_t *table, const Table *dd_table,
867 bool dict_mutex_own);
868
869 /** Make sure the tablespace name is saved in dict_table_t if the table
870 uses a general tablespace.
871 Try to read it from the fil_system_t first, then from DD.
872 @param[in] table Table object
873 @param[in] dd_table Global DD table or partition object
874 @param[in] dict_mutex_own true if dict_sys->mutex is owned already */
875 template <typename Table>
876 void dd_get_and_save_space_name(dict_table_t *table, const Table *dd_table,
877 bool dict_mutex_own);
878
879 /** Get the meta-data filename from the table name for a
880 single-table tablespace.
881 @param[in] table table object
882 @param[in] dd_table DD table object
883 @param[out] filename filename
884 @param[in] max_len filename max length */
885 void dd_get_meta_data_filename(dict_table_t *table, dd::Table *dd_table,
886 char *filename, ulint max_len);
887
888 /** Load foreign key constraint for the table. Note, it could also open
889 the foreign table, if this table is referenced by the foreign table
890 @param[in,out] client data dictionary client
891 @param[in] tbl_name Table Name
892 @param[in] col_names column names, or NULL
893 @param[out] m_table InnoDB table handle
894 @param[in] dd_table Global DD table
895 @param[in] thd thread THD
896 @param[in] dict_locked True if dict_sys->mutex is already held,
897 otherwise false
898 @param[in] check_charsets whether to check charset compatibility
899 @param[in,out] fk_tables name list for tables that refer to this table
900 @return DB_SUCESS if successfully load FK constraint */
901 dberr_t dd_table_load_fk(dd::cache::Dictionary_client *client,
902 const char *tbl_name, const char **col_names,
903 dict_table_t *m_table, const dd::Table *dd_table,
904 THD *thd, bool dict_locked, bool check_charsets,
905 dict_names_t *fk_tables);
906
907 /** Load foreign key constraint for the table. Note, it could also open
908 the foreign table, if this table is referenced by the foreign table
909 @param[in,out] client data dictionary client
910 @param[in] tbl_name Table Name
911 @param[in] col_names column names, or NULL
912 @param[out] m_table InnoDB table handle
913 @param[in] dd_table Global DD table
914 @param[in] thd thread THD
915 @param[in] check_charsets whether to check charset compatibility
916 @param[in] ignore_err DICT_ERR_IGNORE_FK_NOKEY or DICT_ERR_IGNORE_NONE
917 @param[in,out] fk_tables name list for tables that refer to this table
918 @return DB_SUCESS if successfully load FK constraint */
919 dberr_t dd_table_check_for_child(dd::cache::Dictionary_client *client,
920 const char *tbl_name, const char **col_names,
921 dict_table_t *m_table,
922 const dd::Table *dd_table, THD *thd,
923 bool check_charsets,
924 dict_err_ignore_t ignore_err,
925 dict_names_t *fk_tables);
926
927 /** Instantiate an InnoDB in-memory table metadata (dict_table_t)
928 based on a Global DD object.
929 @param[in,out] client data dictionary client
930 @param[in] space_id ID of the tablespace where the table residing
931 @param[in] dd_table Global DD table object
932 @param[in] thd thread THD
933 @param[in] schema_name table schema name
934 @param[in] implicit whether it is file per table tablespace
935 @return error code
936 @retval 0 on success */
937 int dd_table_open_on_dd_obj(dd::cache::Dictionary_client *client,
938 space_id_t space_id, const dd::Table &dd_table,
939 dict_table_t *&table, THD *thd,
940 const dd::String_type *schema_name, bool implicit);
941
942 int dd_table_load_on_dd_obj(dd::cache::Dictionary_client *client,
943 space_id_t space_id, const dd::Table &dd_table,
944 dict_table_t *&table, THD *thd,
945 const dd::String_type *schema_name, bool implicit);
946
947 /** Instantiate an InnoDB in-memory table metadata (dict_table_t)
948 based on a Global DD object.
949 @param[in,out] client data dictionary client
950 @param[in] dd_table Global DD table object
951 @param[in] dd_part Global DD partition or subpartition, or NULL
952 @param[in] tbl_name table name, or NULL if not known
953 @param[out] table InnoDB table (NULL if not found or loadable)
954 @param[in] thd thread THD
955 @return error code
956 @retval 0 on success */
957 int dd_table_open_on_dd_obj(dd::cache::Dictionary_client *client,
958 const dd::Table &dd_table,
959 const dd::Partition *dd_part, const char *tbl_name,
960 dict_table_t *&table, THD *thd);
961 #endif /* !UNIV_HOTBACKUP */
962
963 /** Open a persistent InnoDB table based on table id.
964 @param[in] table_id table identifier
965 @param[in,out] thd current MySQL connection (for mdl)
966 @param[in,out] mdl metadata lock (*mdl set if
967 table_id was found); mdl=NULL if we are resurrecting table IX locks in recovery
968 @param[in] dict_locked dict_sys mutex is held
969 @param[in] check_corruption check if the table is corrupted or not.
970 @return table
971 @retval NULL if the table does not exist or cannot be opened */
972 dict_table_t *dd_table_open_on_id(table_id_t table_id, THD *thd,
973 MDL_ticket **mdl, bool dict_locked,
974 bool check_corruption,
975 bool skip_missing = false);
976
977 /** Close an internal InnoDB table handle.
978 @param[in,out] table InnoDB table handle
979 @param[in,out] thd current MySQL connection (for mdl)
980 @param[in,out] mdl metadata lock (will be set NULL)
981 @param[in] dict_locked whether we hold dict_sys mutex */
982 void dd_table_close(dict_table_t *table, THD *thd, MDL_ticket **mdl,
983 bool dict_locked);
984
985 #ifndef UNIV_HOTBACKUP
986 /** Set the discard flag for a dd table.
987 @param[in,out] thd current thread
988 @param[in] table InnoDB table
989 @param[in] discard discard flag
990 @retval false if fail. */
991 bool dd_table_discard_tablespace(THD *thd, const dict_table_t *table,
992 dd::Table *table_def, bool discard);
993
994 /** Open an internal handle to a persistent InnoDB table by name.
995 @param[in,out] thd current thread
996 @param[out] mdl metadata lock
997 @param[in] name InnoDB table name
998 @param[in] dict_locked has dict_sys mutex locked
999 @param[in] ignore_err whether to ignore err
1000 @param[out] error pointer to error
1001 @return handle to non-partitioned table
1002 @retval NULL if the table does not exist */
1003 dict_table_t *dd_table_open_on_name(THD *thd, MDL_ticket **mdl,
1004 const char *name, bool dict_locked,
1005 ulint ignore_err, int *error = nullptr);
1006
1007 /** Returns a cached table object based on table id.
1008 @param[in] table_id table id
1009 @param[in] dict_locked TRUE=data dictionary locked
1010 @return table, NULL if does not exist */
1011 UNIV_INLINE
1012 dict_table_t *dd_table_open_on_id_in_mem(table_id_t table_id, bool dict_locked);
1013
1014 /** Returns a cached table object based on table name.
1015 @param[in] name table name
1016 @param[in] dict_locked TRUE=data dictionary locked
1017 @return table, NULL if does not exist */
1018 UNIV_INLINE
1019 dict_table_t *dd_table_open_on_name_in_mem(const char *name, ibool dict_locked);
1020
1021 MY_COMPILER_DIAGNOSTIC_PUSH()
1022 MY_COMPILER_CLANG_WORKAROUND_TPARAM_DOCBUG()
1023 /** Open or load a table definition based on a Global DD object.
1024 @tparam Table dd::Table or dd::Partition
1025 @param[in,out] client data dictionary client
1026 @param[in] table MySQL table definition
1027 @param[in] norm_name Table Name
1028 @param[in] dd_table Global DD table or partition object
1029 @param[in] thd thread THD
1030 @return ptr to dict_table_t filled, otherwise, nullptr */
1031 template <typename Table>
1032 dict_table_t *dd_open_table(dd::cache::Dictionary_client *client,
1033 const TABLE *table, const char *norm_name,
1034 const Table *dd_table, THD *thd);
1035 MY_COMPILER_DIAGNOSTIC_POP()
1036
1037 /** Open foreign tables reference a table.
1038 @param[in] fk_list foreign key name list
1039 @param[in] dict_locked dict_sys mutex is locked or not
1040 @param[in] thd thread THD */
1041 void dd_open_fk_tables(dict_names_t &fk_list, bool dict_locked, THD *thd);
1042
1043 /** Update the tablespace name and file name for rename
1044 operation.
1045 @param[in] dd_space_id dd tablespace id
1046 @param[in] is_system_cs true, if space name is in system characters set.
1047 While renaming during bootstrap we have it
1048 in system cs. Othwerwise, in file system cs.
1049 @param[in] new_space_name dd_tablespace name
1050 @param[in] new_path new data file path
1051 @retval DB_SUCCESS on success. */
1052 dberr_t dd_tablespace_rename(dd::Object_id dd_space_id, bool is_system_cs,
1053 const char *new_space_name, const char *new_path);
1054 #endif /* !UNIV_HOTBACKUP */
1055
1056 #ifndef UNIV_HOTBACKUP
1057 /** Create metadata for specified tablespace, acquiring exlcusive MDL first
1058 @param[in,out] dd_client data dictionary client
1059 @param[in,out] thd THD
1060 @param[in,out] dd_space_name dd tablespace name
1061 @param[in] space_id InnoDB tablespace ID
1062 @param[in] flags InnoDB tablespace flags
1063 @param[in] filename filename of this tablespace
1064 @param[in] discarded true if this tablespace was discarded
1065 @param[in,out] dd_space_id dd_space_id
1066 @retval false on success
1067 @retval true on failure */
1068 bool dd_create_tablespace(dd::cache::Dictionary_client *dd_client, THD *thd,
1069 const char *dd_space_name, space_id_t space_id,
1070 uint32_t flags, const char *filename, bool discarded,
1071 dd::Object_id &dd_space_id);
1072
1073 /** Create metadata for implicit tablespace
1074 @param[in,out] dd_client data dictionary client
1075 @param[in,out] thd THD
1076 @param[in] space_id InnoDB tablespace ID
1077 @param[in] space_name tablespace name to be set for the
1078 newly created tablespace
1079 @param[in] filename tablespace filename
1080 @param[in] discarded true if this tablespace was discarded
1081 @param[in,out] dd_space_id dd tablespace id
1082 @retval false on success
1083 @retval true on failure */
1084 bool dd_create_implicit_tablespace(dd::cache::Dictionary_client *dd_client,
1085 THD *thd, space_id_t space_id,
1086 const char *space_name, const char *filename,
1087 bool discarded, dd::Object_id &dd_space_id);
1088
1089 /** Drop a tablespace
1090 @param[in,out] dd_client data dictionary client
1091 @param[in,out] thd THD object
1092 @param[in] dd_space_id dd tablespace id
1093 @retval false On success
1094 @retval true On failure */
1095 bool dd_drop_tablespace(dd::cache::Dictionary_client *dd_client, THD *thd,
1096 dd::Object_id dd_space_id);
1097
1098 /** Obtain the private handler of InnoDB session specific data.
1099 @param[in,out] thd MySQL thread handler.
1100 @return reference to private handler */
1101 MY_ATTRIBUTE((warn_unused_result))
1102 innodb_session_t *&thd_to_innodb_session(THD *thd);
1103
1104 /** Look up a column in a table using the system_charset_info collation.
1105 @param[in] dd_table data dictionary table
1106 @param[in] name column name
1107 @return the column
1108 @retval nullptr if not found */
1109 UNIV_INLINE
1110 const dd::Column *dd_find_column(const dd::Table *dd_table, const char *name);
1111
1112 /** Add a hidden column when creating a table.
1113 @param[in,out] dd_table table containing user columns and indexes
1114 @param[in] name hidden column name
1115 @param[in] length length of the column, in bytes
1116 @param[in] type column type
1117 @return the added column, or NULL if there already was a column by that name */
1118 UNIV_INLINE
1119 dd::Column *dd_add_hidden_column(dd::Table *dd_table, const char *name,
1120 uint length, dd::enum_column_types type);
1121
1122 /** Add a hidden index element at the end.
1123 @param[in,out] index created index metadata
1124 @param[in] column column of the index */
1125 UNIV_INLINE
1126 void dd_add_hidden_element(dd::Index *index, const dd::Column *column);
1127
1128 /** Initialize a hidden unique B-tree index.
1129 @param[in,out] index created index metadata
1130 @param[in] name name of the index
1131 @param[in] column column of the index
1132 @return the initialized index */
1133 UNIV_INLINE
1134 dd::Index *dd_set_hidden_unique_index(dd::Index *index, const char *name,
1135 const dd::Column *column);
1136
1137 /** Check whether there exist a column named as "FTS_DOC_ID", which is
1138 reserved for InnoDB FTS Doc ID
1139 @param[in] thd MySQL thread handle
1140 @param[in] form information on table
1141 columns and indexes
1142 @param[out] doc_id_col Doc ID column number if
1143 there exist a FTS_DOC_ID column,
1144 ULINT_UNDEFINED if column is of the
1145 wrong type/name/size
1146 @return true if there exist a "FTS_DOC_ID" column */
1147 UNIV_INLINE
1148 bool create_table_check_doc_id_col(THD *thd, const TABLE *form,
1149 ulint *doc_id_col);
1150
1151 /** Return a display name for the row format
1152 @param[in] row_format Row Format
1153 @return row format name */
1154 UNIV_INLINE
1155 const char *get_row_format_name(enum row_type row_format);
1156
1157 /** Get the file name of a tablespace.
1158 @param[in] dd_space Tablespace metadata
1159 @return file name */
1160 UNIV_INLINE
dd_tablespace_get_filename(const dd::Tablespace * dd_space)1161 const char *dd_tablespace_get_filename(const dd::Tablespace *dd_space) {
1162 ut_ad(dd_space->id() != dd::INVALID_OBJECT_ID);
1163 ut_ad(dd_space->files().size() == 1);
1164 return ((*dd_space->files().begin())->filename().c_str());
1165 }
1166
1167 /** Check if the InnoDB table is consistent with dd::Table
1168 @tparam Table dd::Table or dd::Partition
1169 @param[in] table InnoDB table
1170 @param[in] dd_table dd::Table or dd::Partition
1171 @return true if match
1172 @retval false if not match */
1173 template <typename Table>
1174 bool dd_table_match(const dict_table_t *table, const Table *dd_table);
1175
1176 /** Create dd table for fts aux index table
1177 @param[in] parent_table parent table of fts table
1178 @param[in,out] table fts table
1179 @param[in] charset fts index charset
1180 @return true on success, false on failure */
1181 bool dd_create_fts_index_table(const dict_table_t *parent_table,
1182 dict_table_t *table,
1183 const CHARSET_INFO *charset);
1184
1185 /** Create dd table for fts aux common table
1186 @param[in] parent_table parent table of fts table
1187 @param[in,out] table fts table
1188 @param[in] is_config flag whether it's fts aux configure table
1189 @return true on success, false on failure */
1190 bool dd_create_fts_common_table(const dict_table_t *parent_table,
1191 dict_table_t *table, bool is_config);
1192
1193 /** Drop dd table & tablespace for fts aux table
1194 @param[in] name table name
1195 @param[in] file_per_table flag whether use file per table
1196 @return true on success, false on failure. */
1197 bool dd_drop_fts_table(const char *name, bool file_per_table);
1198
1199 /** Rename dd table & tablespace files for fts aux table
1200 @param[in] table dict table
1201 @param[in] old_name old innodb table name
1202 @return true on success, false on failure. */
1203 bool dd_rename_fts_table(const dict_table_t *table, const char *old_name);
1204
1205 /** Open a table from its database and table name, this is currently used by
1206 foreign constraint parser to get the referenced table.
1207 @param[in] name foreign key table name
1208 @param[in] database_name table db name
1209 @param[in] database_name_len db name length
1210 @param[in] table_name table db name
1211 @param[in] table_name_len table name length
1212 @param[in,out] table table object or NULL
1213 @param[in,out] mdl mdl on table
1214 @param[in,out] heap heap memory
1215 @return complete table name with database and table name, allocated from
1216 heap memory passed in */
1217 char *dd_get_referenced_table(const char *name, const char *database_name,
1218 ulint database_name_len, const char *table_name,
1219 ulint table_name_len, dict_table_t **table,
1220 MDL_ticket **mdl, mem_heap_t *heap);
1221
1222 /** Set state attribute in se_private_data of tablespace
1223 @param[in,out] dd_space dd::Tablespace object
1224 @param[in] state value to set for key 'state' */
1225 void dd_tablespace_set_state(dd::Tablespace *dd_space, dd_space_states state);
1226
1227 /** Set Space ID and state attribute in se_private_data of mysql.tablespaces
1228 for the named tablespace.
1229 @param[in] space_name tablespace name
1230 @param[in] space_id tablespace id
1231 @param[in] state value to set for key 'state'
1232 @return DB_SUCCESS or DD_FAILURE. */
1233 bool dd_tablespace_set_id_and_state(const char *space_name, space_id_t space_id,
1234 dd_space_states state);
1235
1236 /** Get state attribute value in dd::Tablespace::se_private_data
1237 @param[in] dd_space dd::Tablespace object
1238 @param[in,out] state tablespace state attribute
1239 @param[in] space_id tablespace ID */
1240 void dd_tablespace_get_state(const dd::Tablespace *dd_space,
1241 dd::String_type *state,
1242 space_id_t space_id = SPACE_UNKNOWN);
1243
1244 /** Get state attribute value in dd::Tablespace::se_private_data
1245 @param[in] p dd::Properties for dd::Tablespace::se_private_data
1246 @param[in,out] state tablespace state attribute
1247 @param[in] space_id tablespace ID */
1248 void dd_tablespace_get_state(const dd::Properties *p, dd::String_type *state,
1249 space_id_t space_id = SPACE_UNKNOWN);
1250
1251 /** Get the enum for the state of the undo tablespace
1252 from either dd::Tablespace::se_private_data or undo::Tablespace
1253 @param[in] dd_space dd::Tablespace object
1254 @param[in] space_id tablespace ID
1255 @return enumerated value associated with the key 'state' */
1256 dd_space_states dd_tablespace_get_state_enum(
1257 const dd::Tablespace *dd_space, space_id_t space_id = SPACE_UNKNOWN);
1258
1259 /** Get the enum for the state of the undo tablespace
1260 from either dd::Tablespace::se_private_data or undo::Tablespace
1261 @param[in] p dd::Properties for dd::Tablespace::se_private_data
1262 @param[in] space_id tablespace ID
1263 @return enumerated value associated with the key 'state' */
1264 dd_space_states dd_tablespace_get_state_enum(
1265 const dd::Properties *p, space_id_t space_id = SPACE_UNKNOWN);
1266
1267 /** Get the discarded state from se_private_data of tablespace
1268 @param[in] dd_space dd::Tablespace object */
1269 bool dd_tablespace_is_discarded(const dd::Tablespace *dd_space);
1270
1271 /** Get the MDL for the named tablespace. The mdl_ticket pointer can
1272 be provided if it is needed by the caller. If foreground is set to false,
1273 then the caller must explicitly release that ticket with dd_release_mdl().
1274 Otherwise, it will ne released with the transaction.
1275 @param[in] space_name tablespace name
1276 @param[in] mdl_ticket tablespace MDL ticket, default to nullptr
1277 @param[in] foreground true, if the caller is foreground thread. Default
1278 is true. For foreground, the lock duration is
1279 MDL_TRANSACTION. Otherwise, it is MDL_EXPLICIT.
1280 @return DD_SUCCESS or DD_FAILURE. */
1281 bool dd_tablespace_get_mdl(const char *space_name,
1282 MDL_ticket **mdl_ticket = nullptr,
1283 bool foreground = true);
1284 /** Set discard attribute value in se_private_dat of tablespace
1285 @param[in] dd_space dd::Tablespace object
1286 @param[in] discard true if discarded, else false */
1287 void dd_tablespace_set_discard(dd::Tablespace *dd_space, bool discard);
1288
1289 /** Get discard attribute value stored in se_private_dat of tablespace
1290 @param[in] dd_space dd::Tablespace object
1291 @retval true if Tablespace is discarded
1292 @retval false if attribute doesn't exist or if the
1293 tablespace is not discarded */
1294 bool dd_tablespace_get_discard(const dd::Tablespace *dd_space);
1295
1296 /** Release the MDL held by the given ticket.
1297 @param[in] mdl_ticket tablespace MDL ticket */
1298 void dd_release_mdl(MDL_ticket *mdl_ticket);
1299
1300 #endif /* !UNIV_HOTBACKUP */
1301
1302 /** Update all InnoDB tablespace cache objects. This step is done post
1303 dictionary trx rollback, binlog recovery and DDL_LOG apply. So DD is
1304 consistent. Update the cached tablespace objects, if they differ from
1305 dictionary
1306 @param[in,out] thd thread handle
1307 @retval true on error
1308 @retval false on success */
1309 MY_ATTRIBUTE((warn_unused_result))
1310 bool dd_tablespace_update_cache(THD *thd);
1311
1312 /* Check if the table belongs to an encrypted tablespace.
1313 @return true if it does. */
1314 bool dd_is_table_in_encrypted_tablespace(const dict_table_t *table);
1315
1316 #include "dict0dd.ic"
1317 #endif
1318