| 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 |  | 
|---|