1 /*****************************************************************************
2 
3 Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
4 
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License, version 2.0,
7 as published by the Free Software Foundation.
8 
9 This program is also distributed with certain software (including
10 but not limited to OpenSSL) that is licensed under separate terms,
11 as designated in a particular file or component or in included license
12 documentation.  The authors of MySQL hereby grant you an additional
13 permission to link the program and your derivative works with the
14 separately licensed software that they have included with MySQL.
15 
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 GNU General Public License, version 2.0, 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 Street, Suite 500, Boston, MA 02110-1335 USA
24 
25 *****************************************************************************/
26 
27 /**************************************************//**
28 @file include/dict0load.h
29 Loads to the memory cache database object definitions
30 from dictionary tables
31 
32 Created 4/24/1996 Heikki Tuuri
33 *******************************************************/
34 
35 #ifndef dict0load_h
36 #define dict0load_h
37 
38 #include "univ.i"
39 #include "dict0types.h"
40 #include "trx0types.h"
41 #include "ut0byte.h"
42 #include "mem0mem.h"
43 #include "btr0types.h"
44 
45 /** enum that defines all system table IDs. @see SYSTEM_TABLE_NAME[] */
46 enum dict_system_id_t {
47 	SYS_TABLES = 0,
48 	SYS_INDEXES,
49 	SYS_COLUMNS,
50 	SYS_FIELDS,
51 	SYS_FOREIGN,
52 	SYS_FOREIGN_COLS,
53 	SYS_TABLESPACES,
54 	SYS_DATAFILES,
55 	SYS_ZIP_DICT,
56 	SYS_ZIP_DICT_COLS,
57 
58 	/* This must be last item. Defines the number of system tables. */
59 	SYS_NUM_SYSTEM_TABLES
60 };
61 
62 /** Status bit for dict_process_sys_tables_rec_and_mtr_commit() */
63 enum dict_table_info_t {
64 	DICT_TABLE_LOAD_FROM_RECORD = 0,/*!< Directly populate a dict_table_t
65 					structure with information from
66 					a SYS_TABLES record */
67 	DICT_TABLE_LOAD_FROM_CACHE = 1	/*!< Check first whether dict_table_t
68 					is in the cache, if so, return it */
69 };
70 
71 /** Check type for dict_check_tablespaces_and_store_max_id() */
72 enum dict_check_t {
73 	/** No user tablespaces have been opened
74 	(no crash recovery, no transactions recovered). */
75 	DICT_CHECK_NONE_LOADED = 0,
76 	/** Some user tablespaces may have been opened
77 	(no crash recovery; recovered table locks for transactions). */
78 	DICT_CHECK_SOME_LOADED,
79 	/** All user tablespaces have been opened (crash recovery). */
80 	DICT_CHECK_ALL_LOADED
81 };
82 
83 /********************************************************************//**
84 In a crash recovery we already have all the tablespace objects created.
85 This function compares the space id information in the InnoDB data dictionary
86 to what we already read with fil_load_single_table_tablespaces().
87 
88 In a normal startup, we create the tablespace objects for every table in
89 InnoDB's data dictionary, if the corresponding .ibd file exists.
90 We also scan the biggest space id, and store it to fil_system. */
91 UNIV_INTERN
92 void
93 dict_check_tablespaces_and_store_max_id(
94 /*====================================*/
95 	dict_check_t	dict_check);	/*!< in: how to check */
96 /********************************************************************//**
97 Finds the first table name in the given database.
98 @return own: table name, NULL if does not exist; the caller must free
99 the memory in the string! */
100 UNIV_INTERN
101 char*
102 dict_get_first_table_name_in_db(
103 /*============================*/
104 	const char*	name);	/*!< in: database name which ends to '/' */
105 
106 /********************************************************************//**
107 Loads a table definition from a SYS_TABLES record to dict_table_t.
108 Does not load any columns or indexes.
109 @return error message, or NULL on success */
110 UNIV_INTERN
111 const char*
112 dict_load_table_low(
113 /*================*/
114 	const char*	name,		/*!< in: table name */
115 	const rec_t*	rec,		/*!< in: SYS_TABLES record */
116 	dict_table_t**	table);		/*!< out,own: table, or NULL */
117 /********************************************************************//**
118 Loads a table column definition from a SYS_COLUMNS record to
119 dict_table_t.
120 @return error message, or NULL on success */
121 UNIV_INTERN
122 const char*
123 dict_load_column_low(
124 /*=================*/
125 	dict_table_t*	table,		/*!< in/out: table, could be NULL
126 					if we just populate a dict_column_t
127 					struct with information from
128 					a SYS_COLUMNS record */
129 	mem_heap_t*	heap,		/*!< in/out: memory heap
130 					for temporary storage */
131 	dict_col_t*	column,		/*!< out: dict_column_t to fill,
132 					or NULL if table != NULL */
133 	table_id_t*	table_id,	/*!< out: table id */
134 	const char**	col_name,	/*!< out: column name */
135 	const rec_t*	rec);		/*!< in: SYS_COLUMNS record */
136 /********************************************************************//**
137 Loads an index definition from a SYS_INDEXES record to dict_index_t.
138 If allocate=TRUE, we will create a dict_index_t structure and fill it
139 accordingly. If allocated=FALSE, the dict_index_t will be supplied by
140 the caller and filled with information read from the record.  @return
141 error message, or NULL on success */
142 UNIV_INTERN
143 const char*
144 dict_load_index_low(
145 /*================*/
146 	byte*		table_id,	/*!< in/out: table id (8 bytes),
147 					an "in" value if allocate=TRUE
148 					and "out" when allocate=FALSE */
149 	const char*	table_name,	/*!< in: table name */
150 	mem_heap_t*	heap,		/*!< in/out: temporary memory heap */
151 	const rec_t*	rec,		/*!< in: SYS_INDEXES record */
152 	ibool		allocate,	/*!< in: TRUE=allocate *index,
153 					FALSE=fill in a pre-allocated
154 					*index */
155 	dict_index_t**	index);		/*!< out,own: index, or NULL */
156 /********************************************************************//**
157 Loads an index field definition from a SYS_FIELDS record to
158 dict_index_t.
159 @return error message, or NULL on success */
160 UNIV_INTERN
161 const char*
162 dict_load_field_low(
163 /*================*/
164 	byte*		index_id,	/*!< in/out: index id (8 bytes)
165 					an "in" value if index != NULL
166 					and "out" if index == NULL */
167 	dict_index_t*	index,		/*!< in/out: index, could be NULL
168 					if we just populate a dict_field_t
169 					struct with information from
170 					a SYS_FIELDS record */
171 	dict_field_t*	sys_field,	/*!< out: dict_field_t to be
172 					filled */
173 	ulint*		pos,		/*!< out: Field position */
174 	byte*		last_index_id,	/*!< in: last index id */
175 	mem_heap_t*	heap,		/*!< in/out: memory heap
176 					for temporary storage */
177 	const rec_t*	rec);		/*!< in: SYS_FIELDS record */
178 /********************************************************************//**
179 Using the table->heap, copy the null-terminated filepath into
180 table->data_dir_path and put a null byte before the extension.
181 This allows SHOW CREATE TABLE to return the correct DATA DIRECTORY path.
182 Make this data directory path only if it has not yet been saved. */
183 UNIV_INTERN
184 void
185 dict_save_data_dir_path(
186 /*====================*/
187 	dict_table_t*	table,		/*!< in/out: table */
188 	char*		filepath);	/*!< in: filepath of tablespace */
189 /*****************************************************************//**
190 Make sure the data_file_name is saved in dict_table_t if needed. Try to
191 read it from the file dictionary first, then from SYS_DATAFILES. */
192 UNIV_INTERN
193 void
194 dict_get_and_save_data_dir_path(
195 /*============================*/
196 	dict_table_t*	table,		/*!< in/out: table */
197 	bool		dict_mutex_own);	/*!< in: true if dict_sys->mutex
198 					is owned already */
199 /********************************************************************//**
200 Loads a table definition and also all its index definitions, and also
201 the cluster definition if the table is a member in a cluster. Also loads
202 all foreign key constraints where the foreign key is in the table or where
203 a foreign key references columns in this table.
204 @return table, NULL if does not exist; if the table is stored in an
205 .ibd file, but the file does not exist, then we set the
206 ibd_file_missing flag TRUE in the table object we return */
207 UNIV_INTERN
208 dict_table_t*
209 dict_load_table(
210 /*============*/
211 	const char*	name,	/*!< in: table name in the
212 				databasename/tablename format */
213 	ibool		cached,	/*!< in: TRUE=add to cache, FALSE=do not */
214 	dict_err_ignore_t ignore_err);
215 				/*!< in: error to be ignored when loading
216 				table and its indexes' definition */
217 /***********************************************************************//**
218 Loads a table object based on the table id.
219 @return	table; NULL if table does not exist */
220 UNIV_INTERN
221 dict_table_t*
222 dict_load_table_on_id(
223 /*==================*/
224 	table_id_t		table_id,	/*!< in: table id */
225 	dict_err_ignore_t	ignore_err);	/*!< in: errors to ignore
226 						when loading the table */
227 /********************************************************************//**
228 This function is called when the database is booted.
229 Loads system table index definitions except for the clustered index which
230 is added to the dictionary cache at booting before calling this function. */
231 UNIV_INTERN
232 void
233 dict_load_sys_table(
234 /*================*/
235 	dict_table_t*	table);	/*!< in: system table */
236 /***********************************************************************//**
237 Loads foreign key constraints where the table is either the foreign key
238 holder or where the table is referenced by a foreign key. Adds these
239 constraints to the data dictionary. Note that we know that the dictionary
240 cache already contains all constraints where the other relevant table is
241 already in the dictionary cache.
242 @return	DB_SUCCESS or error code */
243 UNIV_INTERN
244 dberr_t
245 dict_load_foreigns(
246 /*===============*/
247 	const char*		table_name,	/*!< in: table name */
248 	const char**		col_names,	/*!< in: column names, or NULL
249 						to use table->col_names */
250 	bool			check_recursive,/*!< in: Whether to check
251 						recursive load of tables
252 						chained by FK */
253 	bool			check_charsets,	/*!< in: whether to check
254 						charset compatibility */
255 	dict_err_ignore_t	ignore_err)	/*!< in: error to be ignored */
256 	MY_ATTRIBUTE((nonnull(1), warn_unused_result));
257 /********************************************************************//**
258 Prints to the standard output information on all tables found in the data
259 dictionary system table. */
260 UNIV_INTERN
261 void
262 dict_print(void);
263 /*============*/
264 
265 /********************************************************************//**
266 This function opens a system table, and return the first record.
267 @return	first record of the system table */
268 UNIV_INTERN
269 const rec_t*
270 dict_startscan_system(
271 /*==================*/
272 	btr_pcur_t*	pcur,		/*!< out: persistent cursor to
273 					the record */
274 	mtr_t*		mtr,		/*!< in: the mini-transaction */
275 	dict_system_id_t system_id);	/*!< in: which system table to open */
276 /********************************************************************//**
277 This function get the next system table record as we scan the table.
278 @return	the record if found, NULL if end of scan. */
279 UNIV_INTERN
280 const rec_t*
281 dict_getnext_system(
282 /*================*/
283 	btr_pcur_t*	pcur,		/*!< in/out: persistent cursor
284 					to the record */
285 	mtr_t*		mtr);		/*!< in: the mini-transaction */
286 /********************************************************************//**
287 This function processes one SYS_TABLES record and populate the dict_table_t
288 struct for the table. Extracted out of dict_print() to be used by
289 both monitor table output and information schema innodb_sys_tables output.
290 @return error message, or NULL on success */
291 UNIV_INTERN
292 const char*
293 dict_process_sys_tables_rec_and_mtr_commit(
294 /*=======================================*/
295 	mem_heap_t*	heap,		/*!< in: temporary memory heap */
296 	const rec_t*	rec,		/*!< in: SYS_TABLES record */
297 	dict_table_t**	table,		/*!< out: dict_table_t to fill */
298 	dict_table_info_t status,	/*!< in: status bit controls
299 					options such as whether we shall
300 					look for dict_table_t from cache
301 					first */
302 	mtr_t*		mtr);		/*!< in/out: mini-transaction,
303 					will be committed */
304 /********************************************************************//**
305 This function parses a SYS_INDEXES record and populate a dict_index_t
306 structure with the information from the record. For detail information
307 about SYS_INDEXES fields, please refer to dict_boot() function.
308 @return error message, or NULL on success */
309 UNIV_INTERN
310 const char*
311 dict_process_sys_indexes_rec(
312 /*=========================*/
313 	mem_heap_t*	heap,		/*!< in/out: heap memory */
314 	const rec_t*	rec,		/*!< in: current SYS_INDEXES rec */
315 	dict_index_t*	index,		/*!< out: dict_index_t to be
316 					filled */
317 	table_id_t*	table_id);	/*!< out: table id */
318 /********************************************************************//**
319 This function parses a SYS_COLUMNS record and populate a dict_column_t
320 structure with the information from the record.
321 @return error message, or NULL on success */
322 UNIV_INTERN
323 const char*
324 dict_process_sys_columns_rec(
325 /*=========================*/
326 	mem_heap_t*	heap,		/*!< in/out: heap memory */
327 	const rec_t*	rec,		/*!< in: current SYS_COLUMNS rec */
328 	dict_col_t*	column,		/*!< out: dict_col_t to be filled */
329 	table_id_t*	table_id,	/*!< out: table id */
330 	const char**	col_name);	/*!< out: column name */
331 /********************************************************************//**
332 This function parses a SYS_FIELDS record and populate a dict_field_t
333 structure with the information from the record.
334 @return error message, or NULL on success */
335 UNIV_INTERN
336 const char*
337 dict_process_sys_fields_rec(
338 /*========================*/
339 	mem_heap_t*	heap,		/*!< in/out: heap memory */
340 	const rec_t*	rec,		/*!< in: current SYS_FIELDS rec */
341 	dict_field_t*	sys_field,	/*!< out: dict_field_t to be
342 					filled */
343 	ulint*		pos,		/*!< out: Field position */
344 	index_id_t*	index_id,	/*!< out: current index id */
345 	index_id_t	last_id);	/*!< in: previous index id */
346 /********************************************************************//**
347 This function parses a SYS_FOREIGN record and populate a dict_foreign_t
348 structure with the information from the record. For detail information
349 about SYS_FOREIGN fields, please refer to dict_load_foreign() function
350 @return error message, or NULL on success */
351 UNIV_INTERN
352 const char*
353 dict_process_sys_foreign_rec(
354 /*=========================*/
355 	mem_heap_t*	heap,		/*!< in/out: heap memory */
356 	const rec_t*	rec,		/*!< in: current SYS_FOREIGN rec */
357 	dict_foreign_t*	foreign);	/*!< out: dict_foreign_t to be
358 					filled */
359 /********************************************************************//**
360 This function parses a SYS_FOREIGN_COLS record and extract necessary
361 information from the record and return to caller.
362 @return error message, or NULL on success */
363 UNIV_INTERN
364 const char*
365 dict_process_sys_foreign_col_rec(
366 /*=============================*/
367 	mem_heap_t*	heap,		/*!< in/out: heap memory */
368 	const rec_t*	rec,		/*!< in: current SYS_FOREIGN_COLS rec */
369 	const char**	name,		/*!< out: foreign key constraint name */
370 	const char**	for_col_name,	/*!< out: referencing column name */
371 	const char**	ref_col_name,	/*!< out: referenced column name
372 					in referenced table */
373 	ulint*		pos);		/*!< out: column position */
374 /********************************************************************//**
375 This function parses a SYS_TABLESPACES record, extracts necessary
376 information from the record and returns to caller.
377 @return error message, or NULL on success */
378 UNIV_INTERN
379 const char*
380 dict_process_sys_tablespaces(
381 /*=========================*/
382 	mem_heap_t*	heap,		/*!< in/out: heap memory */
383 	const rec_t*	rec,		/*!< in: current SYS_TABLESPACES rec */
384 	ulint*		space,		/*!< out: pace id */
385 	const char**	name,		/*!< out: tablespace name */
386 	ulint*		flags);		/*!< out: tablespace flags */
387 /********************************************************************//**
388 This function parses a SYS_DATAFILES record, extracts necessary
389 information from the record and returns to caller.
390 @return error message, or NULL on success */
391 UNIV_INTERN
392 const char*
393 dict_process_sys_datafiles(
394 /*=======================*/
395 	mem_heap_t*	heap,		/*!< in/out: heap memory */
396 	const rec_t*	rec,		/*!< in: current SYS_DATAFILES rec */
397 	ulint*		space,		/*!< out: pace id */
398 	const char**	path);		/*!< out: datafile path */
399 
400 /** This function parses a SYS_ZIP_DICT record, extracts necessary
401 information from the record and returns to caller.
402 @return error message, or NULL on success */
403 UNIV_INTERN
404 const char*
405 dict_process_sys_zip_dict(
406 	mem_heap_t*	heap,		/*!< in/out: heap memory */
407 	ulint		zip_size,	/*!< in: nonzero=compressed BLOB page size */
408 	const rec_t*	rec,		/*!< in: current SYS_ZIP_DICT rec */
409 	ulint*		id,		/*!< out: dict id */
410 	const char**	name,		/*!< out: dict name */
411 	const char**	data,		/*!< out: dict data */
412 	ulint*		data_len);	/*!< out: dict data length */
413 
414 /** This function parses a SYS_ZIP_DICT_COLS record, extracts necessary
415 information from the record and returns to caller.
416 @return error message, or NULL on success */
417 UNIV_INTERN
418 const char*
419 dict_process_sys_zip_dict_cols(
420 	mem_heap_t*	heap,		/*!< in/out: heap memory */
421 	const rec_t*	rec,		/*!< in: current SYS_ZIP_DICT rec */
422 	ulint*		table_id,	/*!< out: table id */
423 	ulint*		column_pos,	/*!< out: column position */
424 	ulint*		dict_id);	/*!< out: dict id */
425 
426 /********************************************************************//**
427 Get the filepath for a spaceid from SYS_DATAFILES. This function provides
428 a temporary heap which is used for the table lookup, but not for the path.
429 The caller must free the memory for the path returned. This function can
430 return NULL if the space ID is not found in SYS_DATAFILES, then the caller
431 will assume that the ibd file is in the normal datadir.
432 @return	own: A copy of the first datafile found in SYS_DATAFILES.PATH for
433 the given space ID. NULL if space ID is zero or not found. */
434 UNIV_INTERN
435 char*
436 dict_get_first_path(
437 /*================*/
438 	ulint		space,	/*!< in: space id */
439 	const char*	name);	/*!< in: tablespace name */
440 /********************************************************************//**
441 Update the record for space_id in SYS_TABLESPACES to this filepath.
442 @return	DB_SUCCESS if OK, dberr_t if the insert failed */
443 UNIV_INTERN
444 dberr_t
445 dict_update_filepath(
446 /*=================*/
447 	ulint		space_id,	/*!< in: space id */
448 	const char*	filepath);	/*!< in: filepath */
449 /********************************************************************//**
450 Insert records into SYS_TABLESPACES and SYS_DATAFILES.
451 @return	DB_SUCCESS if OK, dberr_t if the insert failed */
452 UNIV_INTERN
453 dberr_t
454 dict_insert_tablespace_and_filepath(
455 /*================================*/
456 	ulint		space,		/*!< in: space id */
457 	const char*	name,		/*!< in: talespace name */
458 	const char*	filepath,	/*!< in: filepath */
459 	ulint		fsp_flags);	/*!< in: tablespace flags */
460 
461 #ifndef UNIV_NONINL
462 #include "dict0load.ic"
463 #endif
464 
465 #endif
466