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