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