| 1 | /***************************************************************************** |
| 2 | |
| 3 | Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. |
| 4 | Copyright (c) 2017, 2018, MariaDB Corporation. |
| 5 | |
| 6 | This program is free software; you can redistribute it and/or modify it under |
| 7 | the terms of the GNU General Public License as published by the Free Software |
| 8 | Foundation; version 2 of the License. |
| 9 | |
| 10 | This program is distributed in the hope that it will be useful, but WITHOUT |
| 11 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
| 12 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
| 13 | |
| 14 | You should have received a copy of the GNU General Public License along with |
| 15 | this program; if not, write to the Free Software Foundation, Inc., |
| 16 | 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA |
| 17 | |
| 18 | *****************************************************************************/ |
| 19 | |
| 20 | /**************************************************//** |
| 21 | @file include/dict0load.h |
| 22 | Loads to the memory cache database object definitions |
| 23 | from dictionary tables |
| 24 | |
| 25 | Created 4/24/1996 Heikki Tuuri |
| 26 | *******************************************************/ |
| 27 | |
| 28 | #ifndef dict0load_h |
| 29 | #define dict0load_h |
| 30 | |
| 31 | #include "univ.i" |
| 32 | #include "dict0types.h" |
| 33 | #include "trx0types.h" |
| 34 | #include "ut0byte.h" |
| 35 | #include "mem0mem.h" |
| 36 | #include "btr0types.h" |
| 37 | #include "ut0new.h" |
| 38 | |
| 39 | #include <deque> |
| 40 | |
| 41 | /** A stack of table names related through foreign key constraints */ |
| 42 | typedef std::deque<const char*, ut_allocator<const char*> > dict_names_t; |
| 43 | |
| 44 | /** enum that defines all system table IDs. @see SYSTEM_TABLE_NAME[] */ |
| 45 | enum dict_system_id_t { |
| 46 | SYS_TABLES = 0, |
| 47 | SYS_INDEXES, |
| 48 | SYS_COLUMNS, |
| 49 | SYS_FIELDS, |
| 50 | SYS_FOREIGN, |
| 51 | SYS_FOREIGN_COLS, |
| 52 | SYS_TABLESPACES, |
| 53 | SYS_DATAFILES, |
| 54 | SYS_VIRTUAL, |
| 55 | |
| 56 | /* This must be last item. Defines the number of system tables. */ |
| 57 | SYS_NUM_SYSTEM_TABLES |
| 58 | }; |
| 59 | |
| 60 | /** Check each tablespace found in the data dictionary. |
| 61 | Look at each table defined in SYS_TABLES that has a space_id > 0. |
| 62 | If the tablespace is not yet in the fil_system cache, look up the |
| 63 | tablespace in SYS_DATAFILES to ensure the correct path. |
| 64 | |
| 65 | In a crash recovery we already have some tablespace objects created from |
| 66 | processing the REDO log. Any other tablespace in SYS_TABLESPACES not |
| 67 | previously used in recovery will be opened here. We will compare the |
| 68 | space_id information in the data dictionary to what we find in the |
| 69 | tablespace file. In addition, more validation will be done if recovery |
| 70 | was needed and force_recovery is not set. |
| 71 | |
| 72 | We also scan the biggest space id, and store it to fil_system. |
| 73 | @param[in] validate true if recovery was needed */ |
| 74 | void |
| 75 | dict_check_tablespaces_and_store_max_id( |
| 76 | bool validate); |
| 77 | |
| 78 | /********************************************************************//** |
| 79 | Finds the first table name in the given database. |
| 80 | @return own: table name, NULL if does not exist; the caller must free |
| 81 | the memory in the string! */ |
| 82 | char* |
| 83 | dict_get_first_table_name_in_db( |
| 84 | /*============================*/ |
| 85 | const char* name); /*!< in: database name which ends to '/' */ |
| 86 | |
| 87 | /** Get the first filepath from SYS_DATAFILES for a given space_id. |
| 88 | @param[in] space_id Tablespace ID |
| 89 | @return First filepath (caller must invoke ut_free() on it) |
| 90 | @retval NULL if no SYS_DATAFILES entry was found. */ |
| 91 | char* |
| 92 | dict_get_first_path( |
| 93 | ulint space_id); |
| 94 | |
| 95 | /** Make sure the data_file_name is saved in dict_table_t if needed. |
| 96 | Try to read it from the fil_system first, then from SYS_DATAFILES. |
| 97 | @param[in] table Table object |
| 98 | @param[in] dict_mutex_own true if dict_sys->mutex is owned already */ |
| 99 | void |
| 100 | dict_get_and_save_data_dir_path( |
| 101 | dict_table_t* table, |
| 102 | bool dict_mutex_own); |
| 103 | |
| 104 | /** Loads a table definition and also all its index definitions, and also |
| 105 | the cluster definition if the table is a member in a cluster. Also loads |
| 106 | all foreign key constraints where the foreign key is in the table or where |
| 107 | a foreign key references columns in this table. |
| 108 | @param[in] name Table name in the dbname/tablename format |
| 109 | @param[in] cached true=add to cache, false=do not |
| 110 | @param[in] ignore_err Error to be ignored when loading |
| 111 | table and its index definition |
| 112 | @return table, NULL if does not exist; if the table is stored in an |
| 113 | .ibd file, but the file does not exist, then we set the file_unreadable |
| 114 | flag in the table object we return. */ |
| 115 | dict_table_t* |
| 116 | dict_load_table( |
| 117 | const char* name, |
| 118 | bool cached, |
| 119 | dict_err_ignore_t ignore_err); |
| 120 | |
| 121 | /***********************************************************************//** |
| 122 | Loads a table object based on the table id. |
| 123 | @return table; NULL if table does not exist */ |
| 124 | dict_table_t* |
| 125 | dict_load_table_on_id( |
| 126 | /*==================*/ |
| 127 | table_id_t table_id, /*!< in: table id */ |
| 128 | dict_err_ignore_t ignore_err); /*!< in: errors to ignore |
| 129 | when loading the table */ |
| 130 | /********************************************************************//** |
| 131 | This function is called when the database is booted. |
| 132 | Loads system table index definitions except for the clustered index which |
| 133 | is added to the dictionary cache at booting before calling this function. */ |
| 134 | void |
| 135 | dict_load_sys_table( |
| 136 | /*================*/ |
| 137 | dict_table_t* table); /*!< in: system table */ |
| 138 | /***********************************************************************//** |
| 139 | Loads foreign key constraints where the table is either the foreign key |
| 140 | holder or where the table is referenced by a foreign key. Adds these |
| 141 | constraints to the data dictionary. |
| 142 | |
| 143 | The foreign key constraint is loaded only if the referenced table is also |
| 144 | in the dictionary cache. If the referenced table is not in dictionary |
| 145 | cache, then it is added to the output parameter (fk_tables). |
| 146 | |
| 147 | @return DB_SUCCESS or error code */ |
| 148 | dberr_t |
| 149 | dict_load_foreigns( |
| 150 | /*===============*/ |
| 151 | const char* table_name, /*!< in: table name */ |
| 152 | const char** col_names, /*!< in: column names, or NULL |
| 153 | to use table->col_names */ |
| 154 | bool check_recursive,/*!< in: Whether to check |
| 155 | recursive load of tables |
| 156 | chained by FK */ |
| 157 | bool check_charsets, /*!< in: whether to check |
| 158 | charset compatibility */ |
| 159 | dict_err_ignore_t ignore_err, /*!< in: error to be ignored */ |
| 160 | dict_names_t& fk_tables) /*!< out: stack of table names |
| 161 | which must be loaded |
| 162 | subsequently to load all the |
| 163 | foreign key constraints. */ |
| 164 | MY_ATTRIBUTE((nonnull(1), warn_unused_result)); |
| 165 | |
| 166 | /********************************************************************//** |
| 167 | This function opens a system table, and return the first record. |
| 168 | @return first record of the system table */ |
| 169 | const rec_t* |
| 170 | dict_startscan_system( |
| 171 | /*==================*/ |
| 172 | btr_pcur_t* pcur, /*!< out: persistent cursor to |
| 173 | the record */ |
| 174 | mtr_t* mtr, /*!< in: the mini-transaction */ |
| 175 | dict_system_id_t system_id); /*!< in: which system table to open */ |
| 176 | /********************************************************************//** |
| 177 | This function get the next system table record as we scan the table. |
| 178 | @return the record if found, NULL if end of scan. */ |
| 179 | const rec_t* |
| 180 | dict_getnext_system( |
| 181 | /*================*/ |
| 182 | btr_pcur_t* pcur, /*!< in/out: persistent cursor |
| 183 | to the record */ |
| 184 | mtr_t* mtr); /*!< in: the mini-transaction */ |
| 185 | /********************************************************************//** |
| 186 | This function processes one SYS_TABLES record and populate the dict_table_t |
| 187 | struct for the table. |
| 188 | @return error message, or NULL on success */ |
| 189 | const char* |
| 190 | dict_process_sys_tables_rec_and_mtr_commit( |
| 191 | /*=======================================*/ |
| 192 | mem_heap_t* heap, /*!< in: temporary memory heap */ |
| 193 | const rec_t* rec, /*!< in: SYS_TABLES record */ |
| 194 | dict_table_t** table, /*!< out: dict_table_t to fill */ |
| 195 | bool cached, /*!< in: whether to load from cache */ |
| 196 | mtr_t* mtr); /*!< in/out: mini-transaction, |
| 197 | will be committed */ |
| 198 | /********************************************************************//** |
| 199 | This function parses a SYS_INDEXES record and populate a dict_index_t |
| 200 | structure with the information from the record. For detail information |
| 201 | about SYS_INDEXES fields, please refer to dict_boot() function. |
| 202 | @return error message, or NULL on success */ |
| 203 | const char* |
| 204 | dict_process_sys_indexes_rec( |
| 205 | /*=========================*/ |
| 206 | mem_heap_t* heap, /*!< in/out: heap memory */ |
| 207 | const rec_t* rec, /*!< in: current SYS_INDEXES rec */ |
| 208 | dict_index_t* index, /*!< out: dict_index_t to be |
| 209 | filled */ |
| 210 | table_id_t* table_id); /*!< out: table id */ |
| 211 | /********************************************************************//** |
| 212 | This function parses a SYS_COLUMNS record and populate a dict_column_t |
| 213 | structure with the information from the record. |
| 214 | @return error message, or NULL on success */ |
| 215 | const char* |
| 216 | dict_process_sys_columns_rec( |
| 217 | /*=========================*/ |
| 218 | mem_heap_t* heap, /*!< in/out: heap memory */ |
| 219 | const rec_t* rec, /*!< in: current SYS_COLUMNS rec */ |
| 220 | dict_col_t* column, /*!< out: dict_col_t to be filled */ |
| 221 | table_id_t* table_id, /*!< out: table id */ |
| 222 | const char** col_name, /*!< out: column name */ |
| 223 | ulint* nth_v_col); /*!< out: if virtual col, this is |
| 224 | records its sequence number */ |
| 225 | |
| 226 | /** This function parses a SYS_VIRTUAL record and extract virtual column |
| 227 | information |
| 228 | @param[in,out] heap heap memory |
| 229 | @param[in] rec current SYS_COLUMNS rec |
| 230 | @param[in,out] table_id table id |
| 231 | @param[in,out] pos virtual column position |
| 232 | @param[in,out] base_pos base column position |
| 233 | @return error message, or NULL on success */ |
| 234 | const char* |
| 235 | dict_process_sys_virtual_rec( |
| 236 | const rec_t* rec, |
| 237 | table_id_t* table_id, |
| 238 | ulint* pos, |
| 239 | ulint* base_pos); |
| 240 | /********************************************************************//** |
| 241 | This function parses a SYS_FIELDS record and populate a dict_field_t |
| 242 | structure with the information from the record. |
| 243 | @return error message, or NULL on success */ |
| 244 | const char* |
| 245 | dict_process_sys_fields_rec( |
| 246 | /*========================*/ |
| 247 | mem_heap_t* heap, /*!< in/out: heap memory */ |
| 248 | const rec_t* rec, /*!< in: current SYS_FIELDS rec */ |
| 249 | dict_field_t* sys_field, /*!< out: dict_field_t to be |
| 250 | filled */ |
| 251 | ulint* pos, /*!< out: Field position */ |
| 252 | index_id_t* index_id, /*!< out: current index id */ |
| 253 | index_id_t last_id); /*!< in: previous index id */ |
| 254 | /********************************************************************//** |
| 255 | This function parses a SYS_FOREIGN record and populate a dict_foreign_t |
| 256 | structure with the information from the record. For detail information |
| 257 | about SYS_FOREIGN fields, please refer to dict_load_foreign() function |
| 258 | @return error message, or NULL on success */ |
| 259 | const char* |
| 260 | dict_process_sys_foreign_rec( |
| 261 | /*=========================*/ |
| 262 | mem_heap_t* heap, /*!< in/out: heap memory */ |
| 263 | const rec_t* rec, /*!< in: current SYS_FOREIGN rec */ |
| 264 | dict_foreign_t* foreign); /*!< out: dict_foreign_t to be |
| 265 | filled */ |
| 266 | /********************************************************************//** |
| 267 | This function parses a SYS_FOREIGN_COLS record and extract necessary |
| 268 | information from the record and return to caller. |
| 269 | @return error message, or NULL on success */ |
| 270 | const char* |
| 271 | dict_process_sys_foreign_col_rec( |
| 272 | /*=============================*/ |
| 273 | mem_heap_t* heap, /*!< in/out: heap memory */ |
| 274 | const rec_t* rec, /*!< in: current SYS_FOREIGN_COLS rec */ |
| 275 | const char** name, /*!< out: foreign key constraint name */ |
| 276 | const char** for_col_name, /*!< out: referencing column name */ |
| 277 | const char** ref_col_name, /*!< out: referenced column name |
| 278 | in referenced table */ |
| 279 | ulint* pos); /*!< out: column position */ |
| 280 | /********************************************************************//** |
| 281 | This function parses a SYS_TABLESPACES record, extracts necessary |
| 282 | information from the record and returns to caller. |
| 283 | @return error message, or NULL on success */ |
| 284 | const char* |
| 285 | dict_process_sys_tablespaces( |
| 286 | /*=========================*/ |
| 287 | mem_heap_t* heap, /*!< in/out: heap memory */ |
| 288 | const rec_t* rec, /*!< in: current SYS_TABLESPACES rec */ |
| 289 | ulint* space, /*!< out: pace id */ |
| 290 | const char** name, /*!< out: tablespace name */ |
| 291 | ulint* flags); /*!< out: tablespace flags */ |
| 292 | /********************************************************************//** |
| 293 | This function parses a SYS_DATAFILES record, extracts necessary |
| 294 | information from the record and returns to caller. |
| 295 | @return error message, or NULL on success */ |
| 296 | const char* |
| 297 | dict_process_sys_datafiles( |
| 298 | /*=======================*/ |
| 299 | mem_heap_t* heap, /*!< in/out: heap memory */ |
| 300 | const rec_t* rec, /*!< in: current SYS_DATAFILES rec */ |
| 301 | ulint* space, /*!< out: pace id */ |
| 302 | const char** path); /*!< out: datafile path */ |
| 303 | |
| 304 | /** Update the record for space_id in SYS_TABLESPACES to this filepath. |
| 305 | @param[in] space_id Tablespace ID |
| 306 | @param[in] filepath Tablespace filepath |
| 307 | @return DB_SUCCESS if OK, dberr_t if the insert failed */ |
| 308 | dberr_t |
| 309 | dict_update_filepath( |
| 310 | ulint space_id, |
| 311 | const char* filepath); |
| 312 | |
| 313 | /** Replace records in SYS_TABLESPACES and SYS_DATAFILES associated with |
| 314 | the given space_id using an independent transaction. |
| 315 | @param[in] space_id Tablespace ID |
| 316 | @param[in] name Tablespace name |
| 317 | @param[in] filepath First filepath |
| 318 | @param[in] fsp_flags Tablespace flags |
| 319 | @return DB_SUCCESS if OK, dberr_t if the insert failed */ |
| 320 | dberr_t |
| 321 | dict_replace_tablespace_and_filepath( |
| 322 | ulint space_id, |
| 323 | const char* name, |
| 324 | const char* filepath, |
| 325 | ulint fsp_flags); |
| 326 | |
| 327 | #endif |
| 328 | |