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