1 /*****************************************************************************
2 
3 Copyright (c) 1996, 2019, 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/dict0types.h
28  Data dictionary global types
29 
30  Created 1/8/1996 Heikki Tuuri
31  *******************************************************/
32 
33 #ifndef dict0types_h
34 #define dict0types_h
35 
36 #include "ibuf0types.h" /* IBUF_SPACE_ID */
37 #include "mysql_com.h"
38 #include "rem0types.h"
39 #include "ut0mutex.h"
40 
41 struct dict_sys_t;
42 struct dict_col_t;
43 struct dict_field_t;
44 struct dict_index_t;
45 struct dict_table_t;
46 struct dict_foreign_t;
47 struct dict_v_col_t;
48 
49 struct ind_node_t;
50 struct tab_node_t;
51 struct dict_add_v_col_t;
52 
53 namespace dd {
54 class Partition;
55 }
56 
57 /** Innodb data dictionary name.
58 NOTE: Innodb dictionary table name is always in my_charset_filename. Hence,
59 dictionary name (dict_name) and partition string input parameters in dict_name::
60 interfaces are assumed to be in my_charset_filename. */
61 namespace dict_name {
62 /** Partition separator in dictionary table name and file name. */
63 constexpr char PART_SEPARATOR[] = "#p#";
64 
65 /** Partition separator length excluding terminating NULL */
66 constexpr size_t PART_SEPARATOR_LEN = sizeof(PART_SEPARATOR) - 1;
67 
68 /** Sub-Partition separator in dictionary table name and file name. */
69 constexpr char SUB_PART_SEPARATOR[] = "#sp#";
70 
71 /** Sub-Partition separator length excluding terminating NULL */
72 constexpr size_t SUB_PART_SEPARATOR_LEN = sizeof(SUB_PART_SEPARATOR) - 1;
73 
74 /** Alternative partition separator from 8.0.17 and older versions. */
75 constexpr char ALT_PART_SEPARATOR[] = "#P#";
76 
77 /** Alternative sub-partition separator from 8.0.17 and older versions. */
78 constexpr char ALT_SUB_PART_SEPARATOR[] = "#SP#";
79 
80 /** Schema separator is forward slash irrespective of platform. */
81 constexpr char SCHEMA_SEPARATOR[] = "/";
82 constexpr size_t SCHEMA_SEPARATOR_LEN = sizeof(SCHEMA_SEPARATOR) - 1;
83 
84 /** The maximum length in bytes that a database name can occupy when
85 stored in UTF8, including the terminating null. */
86 constexpr size_t MAX_DB_UTF8_LEN = NAME_LEN + 1;
87 
88 /** The maximum length in characters for database name. */
89 constexpr size_t MAX_DB_CHAR_LEN = NAME_CHAR_LEN;
90 
91 /** The maximum length in bytes that a table name can occupy when stored in
92 UTF8, including the terminating null. NAME_LEN is added 3 times to consider
93 table name, partition name and sub-partition name for a partitioned table.
94 In innodb each partition/sub-partition is a separate table named as below.
95 table_name<PART_SEPARATOR>partition_name<SUB_PART_SEPARATOR>subpartition_name
96 This macro only applies to table name, without any database name prefixed. */
97 constexpr size_t MAX_TABLE_UTF8_LEN = NAME_LEN + PART_SEPARATOR_LEN + NAME_LEN +
98                                       SUB_PART_SEPARATOR_LEN + NAME_LEN + 1;
99 
100 /** The maximum length in characters for table name. */
101 constexpr size_t MAX_TABLE_CHAR_LEN = NAME_CHAR_LEN + PART_SEPARATOR_LEN +
102                                       NAME_CHAR_LEN + SUB_PART_SEPARATOR_LEN +
103                                       NAME_CHAR_LEN;
104 
105 /** Postfix for a table name which is being altered. Since during
106 ALTER TABLE ... PARTITION, new partitions have to be created before
107 dropping existing partitions, so a postfix is appended to the name
108 to prevent name conflicts. This is also used for EXCHANGE PARTITION */
109 constexpr char TMP_POSTFIX[] = "#tmp";
110 constexpr size_t TMP_POSTFIX_LEN = sizeof(TMP_POSTFIX) - 1;
111 
112 /** Maximum space name length. Space name includes schema name, table name
113 along with partition and sub-partition name for partitioned table. */
114 constexpr size_t MAX_SPACE_NAME_LEN =
115     NAME_LEN + SCHEMA_SEPARATOR_LEN + NAME_LEN + PART_SEPARATOR_LEN + NAME_LEN +
116     SUB_PART_SEPARATOR_LEN + NAME_LEN + TMP_POSTFIX_LEN;
117 
118 /** Name string conversion callback. Used for character set conversion. */
119 using Convert_Func = std::function<void(std::string &)>;
120 
121 /** Conversion function to change for system to file name cs.
122 @param[in,out]	name	identifier name.
123 @param[in]	quiet	true, if we allow error during conversion. */
124 void file_to_table(std::string &name, bool quiet);
125 
126 /** Conversion function to change for file name to system cs.
127 @param[in,out]	name	identifier name. */
128 void table_to_file(std::string &name);
129 
130 /** Check if it is a table partition.
131 @param[in]	dict_name	table name in dictionary
132 @return true, iff it is table partition. */
133 bool is_partition(const std::string &dict_name);
134 
135 /** Get schema, table name, partition string and temporary attribute from
136 dictionary table name.
137 @param[in]	dict_name	table name in dictionary
138 @param[in]	convert		convert schema & table name to system cs
139 @param[out]	schema		schema name
140 @param[out]	table		table name
141 @param[out]	partition	partition string if table partition
142 @param[out]	is_tmp		true, iff temporary table created by DDL */
143 void get_table(const std::string &dict_name, bool convert, std::string &schema,
144                std::string &table, std::string &partition, bool &is_tmp);
145 
146 /** Get schema and table name from dictionary table name.
147 @param[in]	dict_name	table name in dictionary
148 @param[out]	schema		schema name
149 @param[out]	table		table name */
150 void get_table(const std::string &dict_name, std::string &schema,
151                std::string &table);
152 
153 /** Get partition and sub-partition name from partition string
154 @param[in]	partition	partition string from dictionary table name
155 @param[in]	convert		convert partition names to system cs
156 @param[out]	part		partition name
157 @param[out]	sub_part	sub partition name if present */
158 void get_partition(const std::string &partition, bool convert,
159                    std::string &part, std::string &sub_part);
160 
161 /* Build dictionary table name. Table name in dictionary is always in filename
162 character set.
163 @param[in]	schema		schema name
164 @param[in]	table		table name
165 @param[in]	partition	partition string if table partition
166 @param[in]	is_tmp		true, iff temporary table created by DDL
167 @param[in]	convert		convert all names from system cs
168 @param[out]	dict_name	table name for innodb dictionary */
169 void build_table(const std::string &schema, const std::string &table,
170                  const std::string &partition, bool is_tmp, bool convert,
171                  std::string &dict_name);
172 
173 /** Build partition string from dd object.
174 @param[in]	dd_part		partition object from DD
175 @param[out]	partition	partition string for dictionary table name */
176 void build_partition(const dd::Partition *dd_part, std::string &partition);
177 
178 /** Build 5.7 style partition string from dd object.
179 @param[in]	dd_part		partition object from DD
180 @param[out]	partition	partition string for dictionary table name */
181 void build_57_partition(const dd::Partition *dd_part, std::string &partition);
182 
183 /** Check if dd partition matches with innodb dictionary table name.
184 @param[in]	dict_name	table name in innodb dictionary
185 @param[in]	dd_part		partition object from DD
186 @return true, iff the name matches the partition from DD. */
187 bool match_partition(const std::string &dict_name,
188                      const dd::Partition *dd_part);
189 
190 /* Build space name by converting schema, table, partition and sub partition
191 names within a dictionary table name.
192 @param[in,out]	dict_name	table name in dictionary */
193 void convert_to_space(std::string &dict_name);
194 
195 /* Rebuild space name by replacing partition string from dictionary table name.
196 @param[in]	dict_name	table name in dictionary
197 @param[in,out]	space_name	space name to be rebuilt */
198 void rebuild_space(const std::string &dict_name, std::string &space_name);
199 
200 /** Rebuild table name to convert from 5.7 format to 8.0.
201 @param[in,out]	dict_name	table name in dictionary */
202 void rebuild(std::string &dict_name);
203 
204 }  // namespace dict_name
205 
206 /* Space id and page no where the dictionary header resides */
207 #define DICT_HDR_SPACE 0 /* the SYSTEM tablespace */
208 #define DICT_HDR_PAGE_NO FSP_DICT_HDR_PAGE_NO
209 
210 /* The ibuf table and indexes's ID are assigned as the number
211 DICT_IBUF_ID_MIN plus the space id */
212 #define DICT_IBUF_ID_MIN 0xFFFFFFFF00000000ULL
213 
214 /** Table or partition identifier (unique within an InnoDB instance). */
215 typedef ib_id_t table_id_t;
216 /** Index identifier (unique within a tablespace). */
217 typedef ib_id_t space_index_t;
218 
219 /** Globally unique index identifier */
220 class index_id_t {
221  public:
222   /** Constructor.
223   @param[in]	space_id	Tablespace identifier
224   @param[in]	index_id	Index identifier */
index_id_t(space_id_t space_id,space_index_t index_id)225   index_id_t(space_id_t space_id, space_index_t index_id)
226       : m_space_id(space_id), m_index_id(index_id) {}
227 
228   /** Compare this to another index identifier.
229   @param other	the other index identifier
230   @return whether this is less than other */
231   bool operator<(const index_id_t &other) const {
232     return (m_space_id < other.m_space_id ||
233             (m_space_id == other.m_space_id && m_index_id < other.m_index_id));
234   }
235   /** Compare this to another index identifier.
236   @param other	the other index identifier
237   @return whether the identifiers are equal */
238   bool operator==(const index_id_t &other) const {
239     return (m_space_id == other.m_space_id && m_index_id == other.m_index_id);
240   }
241 
242   /** Convert an index_id to a 64 bit integer.
243   @return a 64 bit integer */
conv_to_int()244   uint64_t conv_to_int() const {
245     ut_ad((m_index_id & 0xFFFFFFFF00000000ULL) == 0);
246 
247     return (static_cast<uint64_t>(m_space_id) << 32 | m_index_id);
248   }
249 
250   /** Check if the index belongs to the insert buffer.
251   @return true if the index belongs to the insert buffer */
is_ibuf()252   bool is_ibuf() const {
253     return (m_space_id == IBUF_SPACE_ID &&
254             m_index_id == DICT_IBUF_ID_MIN + IBUF_SPACE_ID);
255   }
256 
257   /** Tablespace identifier */
258   space_id_t m_space_id;
259   /** Index identifier within the tablespace */
260   space_index_t m_index_id;
261 };
262 
263 /** Display an index identifier.
264 @param[in,out]	out	the output stream
265 @param[in]	id	index identifier
266 @return the output stream */
267 inline std::ostream &operator<<(std::ostream &out, const index_id_t &id) {
268   return (out << "[space=" << id.m_space_id << ",index=" << id.m_index_id
269               << "]");
270 }
271 
272 /** Error to ignore when we load table dictionary into memory. However,
273 the table and index will be marked as "corrupted", and caller will
274 be responsible to deal with corrupted table or index.
275 Note: please define the IGNORE_ERR_* as bits, so their value can
276 be or-ed together */
277 enum dict_err_ignore_t {
278   DICT_ERR_IGNORE_NONE = 0,       /*!< no error to ignore */
279   DICT_ERR_IGNORE_INDEX_ROOT = 1, /*!< ignore error if index root
280                                   page is FIL_NULL or incorrect value */
281   DICT_ERR_IGNORE_CORRUPT = 2,    /*!< skip corrupted indexes */
282   DICT_ERR_IGNORE_FK_NOKEY = 4,   /*!< ignore error if any foreign
283                                   key is missing */
284   DICT_ERR_IGNORE_RECOVER_LOCK = 8,
285   /*!< Used when recovering table locks
286   for resurrected transactions.
287   Silently load a missing
288   tablespace, and do not load
289   incomplete index definitions. */
290   DICT_ERR_IGNORE_ALL = 0xFFFF /*!< ignore all errors */
291 };
292 
293 /** Quiescing states for flushing tables to disk. */
294 enum ib_quiesce_t {
295   QUIESCE_NONE,
296   QUIESCE_START,   /*!< Initialise, prepare to start */
297   QUIESCE_COMPLETE /*!< All done */
298 };
299 
300 #ifndef UNIV_HOTBACKUP
301 typedef ib_mutex_t DictSysMutex;
302 #endif /* !UNIV_HOTBACKUP */
303 
304 /** Prefix for tmp tables, adopted from sql/table.h */
305 #define TEMP_FILE_PREFIX "#sql"
306 #define TEMP_FILE_PREFIX_LENGTH 4
307 #define TEMP_FILE_PREFIX_INNODB "#sql-ib"
308 
309 #define TEMP_TABLE_PREFIX "#sql"
310 #define TEMP_TABLE_PATH_PREFIX "/" TEMP_TABLE_PREFIX
311 
312 #if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
313 /** Flag to control insert buffer debugging. */
314 extern uint ibuf_debug;
315 #endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
316 
317 /** Shift for spatial status */
318 #define SPATIAL_STATUS_SHIFT 12
319 
320 /** Mask to encode/decode spatial status. */
321 #define SPATIAL_STATUS_MASK (3 << SPATIAL_STATUS_SHIFT)
322 
323 #if SPATIAL_STATUS_MASK < REC_VERSION_56_MAX_INDEX_COL_LEN
324 #error SPATIAL_STATUS_MASK < REC_VERSION_56_MAX_INDEX_COL_LEN
325 #endif
326 
327 /** whether a col is used in spatial index or regular index
328 Note: the spatial status is part of persistent undo log,
329 so we should not modify the values in MySQL 5.7 */
330 enum spatial_status_t {
331   /* Unkown status (undo format in 5.7.9) */
332   SPATIAL_UNKNOWN = 0,
333 
334   /** Not used in gis index. */
335   SPATIAL_NONE = 1,
336 
337   /** Used in both spatial index and regular index. */
338   SPATIAL_MIXED = 2,
339 
340   /** Only used in spatial index. */
341   SPATIAL_ONLY = 3
342 };
343 
344 #endif
345