dict0load.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:33k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /******************************************************
  2. Loads to the memory cache database object definitions
  3. from dictionary tables
  4. (c) 1996 Innobase Oy
  5. Created 4/24/1996 Heikki Tuuri
  6. *******************************************************/
  7. #include "dict0load.h"
  8. #ifdef UNIV_NONINL
  9. #include "dict0load.ic"
  10. #endif
  11. #include "btr0pcur.h"
  12. #include "btr0btr.h"
  13. #include "page0page.h"
  14. #include "mach0data.h"
  15. #include "dict0dict.h"
  16. #include "dict0boot.h"
  17. #include "rem0cmp.h"
  18. #include "srv0start.h"
  19. #include "srv0srv.h"
  20. /************************************************************************
  21. Finds the first table name in the given database. */
  22. char*
  23. dict_get_first_table_name_in_db(
  24. /*============================*/
  25. /* out, own: table name, NULL if
  26. does not exist; the caller must
  27. free the memory in the string! */
  28. const char* name) /* in: database name which ends in '/' */
  29. {
  30. dict_table_t* sys_tables;
  31. btr_pcur_t pcur;
  32. dict_index_t* sys_index;
  33. dtuple_t* tuple;
  34. mem_heap_t* heap;
  35. dfield_t* dfield;
  36. rec_t* rec;
  37. byte* field;
  38. ulint len;
  39. mtr_t mtr;
  40. #ifdef UNIV_SYNC_DEBUG
  41. ut_ad(mutex_own(&(dict_sys->mutex)));
  42. #endif /* UNIV_SYNC_DEBUG */
  43. heap = mem_heap_create(1000);
  44. mtr_start(&mtr);
  45. sys_tables = dict_table_get_low("SYS_TABLES");
  46. sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
  47. tuple = dtuple_create(heap, 1);
  48. dfield = dtuple_get_nth_field(tuple, 0);
  49. dfield_set_data(dfield, name, ut_strlen(name));
  50. dict_index_copy_types(tuple, sys_index, 1);
  51. btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
  52. BTR_SEARCH_LEAF, &pcur, &mtr);
  53. loop:
  54. rec = btr_pcur_get_rec(&pcur);
  55. if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) {
  56. /* Not found */
  57. btr_pcur_close(&pcur);
  58. mtr_commit(&mtr);
  59. mem_heap_free(heap);
  60. return(NULL);
  61. }
  62. field = rec_get_nth_field(rec, 0, &len);
  63. if (len < strlen(name)
  64.     || ut_memcmp(name, field, strlen(name)) != 0) {
  65. /* Not found */
  66. btr_pcur_close(&pcur);
  67. mtr_commit(&mtr);
  68. mem_heap_free(heap);
  69. return(NULL);
  70. }
  71. if (!rec_get_deleted_flag(rec)) {
  72. /* We found one */
  73.                 char* table_name = mem_strdupl((char*) field, len);
  74. btr_pcur_close(&pcur);
  75. mtr_commit(&mtr);
  76. mem_heap_free(heap);
  77. return(table_name);
  78. }
  79. btr_pcur_move_to_next_user_rec(&pcur, &mtr);
  80. goto loop;
  81. }
  82. /************************************************************************
  83. Prints to the standard output information on all tables found in the data
  84. dictionary system table. */
  85. void
  86. dict_print(void)
  87. /*============*/
  88. {
  89. dict_table_t* sys_tables;
  90. dict_index_t* sys_index;
  91. dict_table_t* table;
  92. btr_pcur_t pcur;
  93. rec_t* rec;
  94. byte* field;
  95. ulint len;
  96. mtr_t mtr;
  97. /* Enlarge the fatal semaphore wait timeout during the InnoDB table
  98. monitor printout */
  99. mutex_enter(&kernel_mutex);
  100. srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
  101. mutex_exit(&kernel_mutex);
  102. mutex_enter(&(dict_sys->mutex));
  103. mtr_start(&mtr);
  104. sys_tables = dict_table_get_low("SYS_TABLES");
  105. sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
  106. btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur,
  107. TRUE, &mtr);
  108. loop:
  109. btr_pcur_move_to_next_user_rec(&pcur, &mtr);
  110. rec = btr_pcur_get_rec(&pcur);
  111. if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) {
  112. /* end of index */
  113. btr_pcur_close(&pcur);
  114. mtr_commit(&mtr);
  115. mutex_exit(&(dict_sys->mutex));
  116. /* Restore the fatal semaphore wait timeout */
  117. mutex_enter(&kernel_mutex);
  118. srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
  119. mutex_exit(&kernel_mutex);
  120. return;
  121. }
  122. field = rec_get_nth_field(rec, 0, &len);
  123. if (!rec_get_deleted_flag(rec)) {
  124. /* We found one */
  125.                 char* table_name = mem_strdupl((char*) field, len);
  126. btr_pcur_store_position(&pcur, &mtr);
  127. mtr_commit(&mtr);
  128. table = dict_table_get_low(table_name);
  129. mem_free(table_name);
  130. if (table == NULL) {
  131. fputs("InnoDB: Failed to load table ", stderr);
  132. ut_print_namel(stderr, NULL, field, len);
  133. putc('n', stderr);
  134. } else {
  135. /* The table definition was corrupt if there
  136. is no index */
  137. if (dict_table_get_first_index(table)) {
  138. dict_update_statistics_low(table, TRUE);
  139. }
  140. dict_table_print_low(table);
  141. }
  142. mtr_start(&mtr);
  143. btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
  144. }
  145. goto loop;
  146. }
  147. /************************************************************************
  148. In a crash recovery we already have all the tablespace objects created.
  149. This function compares the space id information in the InnoDB data dictionary
  150. to what we already read with fil_load_single_table_tablespaces().
  151. In a normal startup, we create the tablespace objects for every table in
  152. InnoDB's data dictionary, if the corresponding .ibd file exists.
  153. We also scan the biggest space id, and store it to fil_system. */
  154. void
  155. dict_check_tablespaces_and_store_max_id(
  156. /*====================================*/
  157. ibool in_crash_recovery) /* in: are we doing a crash recovery */
  158. {
  159. dict_table_t* sys_tables;
  160. dict_index_t* sys_index;
  161. btr_pcur_t pcur;
  162. rec_t* rec;
  163. byte* field;
  164. ulint len;
  165. ulint space_id;
  166. ulint max_space_id = 0;
  167. mtr_t mtr;
  168. mutex_enter(&(dict_sys->mutex));
  169. mtr_start(&mtr);
  170. sys_tables = dict_table_get_low("SYS_TABLES");
  171. sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
  172. btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur,
  173. TRUE, &mtr);
  174. loop:
  175. btr_pcur_move_to_next_user_rec(&pcur, &mtr);
  176. rec = btr_pcur_get_rec(&pcur);
  177. if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) {
  178. /* end of index */
  179. btr_pcur_close(&pcur);
  180. mtr_commit(&mtr);
  181. /* We must make the tablespace cache aware of the biggest
  182. known space id */
  183. /* printf("Biggest space id in data dictionary %lun",
  184.     max_space_id); */
  185. fil_set_max_space_id_if_bigger(max_space_id);
  186. mutex_exit(&(dict_sys->mutex));
  187. return;
  188. }
  189. field = rec_get_nth_field(rec, 0, &len);
  190. if (!rec_get_deleted_flag(rec)) {
  191. /* We found one */
  192.                 char* name = mem_strdupl((char*) field, len);
  193. field = rec_get_nth_field(rec, 9, &len);
  194. ut_a(len == 4);
  195. space_id = mach_read_from_4(field);
  196. btr_pcur_store_position(&pcur, &mtr);
  197. mtr_commit(&mtr);
  198. if (space_id != 0 && in_crash_recovery) {
  199. /* Check that the tablespace (the .ibd file) really
  200. exists; print a warning to the .err log if not */
  201. fil_space_for_table_exists_in_mem(space_id, name,
  202. FALSE, TRUE, TRUE);
  203. }
  204. if (space_id != 0 && !in_crash_recovery) {
  205. /* It is a normal database startup: create the space
  206. object and check that the .ibd file exists. */
  207. fil_open_single_table_tablespace(FALSE, space_id,
  208. name);
  209. }
  210. mem_free(name);
  211. if (space_id > max_space_id) {
  212. max_space_id = space_id;
  213. }
  214. mtr_start(&mtr);
  215. btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
  216. }
  217. goto loop;
  218. }
  219. /************************************************************************
  220. Loads definitions for table columns. */
  221. static
  222. void
  223. dict_load_columns(
  224. /*==============*/
  225. dict_table_t* table, /* in: table */
  226. mem_heap_t* heap) /* in: memory heap for temporary storage */
  227. {
  228. dict_table_t* sys_columns;
  229. dict_index_t* sys_index;
  230. btr_pcur_t pcur;
  231. dtuple_t* tuple;
  232. dfield_t* dfield;
  233. rec_t* rec;
  234. byte* field;
  235. ulint len;
  236. byte* buf;
  237. char* name;
  238. ulint mtype;
  239. ulint prtype;
  240. ulint col_len;
  241. ulint prec;
  242. ulint i;
  243. mtr_t mtr;
  244. #ifdef UNIV_SYNC_DEBUG
  245. ut_ad(mutex_own(&(dict_sys->mutex)));
  246. #endif /* UNIV_SYNC_DEBUG */
  247. mtr_start(&mtr);
  248. sys_columns = dict_table_get_low("SYS_COLUMNS");
  249. sys_index = UT_LIST_GET_FIRST(sys_columns->indexes);
  250. tuple = dtuple_create(heap, 1);
  251. dfield = dtuple_get_nth_field(tuple, 0);
  252. buf = mem_heap_alloc(heap, 8);
  253. mach_write_to_8(buf, table->id);
  254. dfield_set_data(dfield, buf, 8);
  255. dict_index_copy_types(tuple, sys_index, 1);
  256. btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
  257. BTR_SEARCH_LEAF, &pcur, &mtr);
  258.     for (i = 0; i < table->n_cols - DATA_N_SYS_COLS; i++) {
  259. rec = btr_pcur_get_rec(&pcur);
  260. ut_a(btr_pcur_is_on_user_rec(&pcur, &mtr));
  261. ut_a(!rec_get_deleted_flag(rec));
  262. field = rec_get_nth_field(rec, 0, &len);
  263. ut_ad(len == 8);
  264. ut_a(ut_dulint_cmp(table->id, mach_read_from_8(field)) == 0);
  265. field = rec_get_nth_field(rec, 1, &len);
  266. ut_ad(len == 4);
  267. ut_a(i == mach_read_from_4(field));
  268. ut_a(0 == ut_strcmp("NAME",
  269. dict_field_get_col(
  270. dict_index_get_nth_field(
  271. dict_table_get_first_index(sys_columns), 4))->name));
  272. field = rec_get_nth_field(rec, 4, &len);
  273. name = mem_heap_strdupl(heap, (char*) field, len);
  274. field = rec_get_nth_field(rec, 5, &len);
  275. mtype = mach_read_from_4(field);
  276. field = rec_get_nth_field(rec, 6, &len);
  277. prtype = mach_read_from_4(field);
  278. if (dtype_is_non_binary_string_type(mtype, prtype)
  279.     && dtype_get_charset_coll(prtype) == 0) {
  280. /* This is a non-binary string type, and the table
  281. was created with < 4.1.2. Use the default charset. */
  282. prtype = dtype_form_prtype(prtype,
  283. data_mysql_default_charset_coll);
  284. }
  285. field = rec_get_nth_field(rec, 7, &len);
  286. col_len = mach_read_from_4(field);
  287. ut_a(0 == ut_strcmp("PREC",
  288. dict_field_get_col(
  289. dict_index_get_nth_field(
  290. dict_table_get_first_index(sys_columns), 8))->name));
  291. field = rec_get_nth_field(rec, 8, &len);
  292. prec = mach_read_from_4(field);
  293. dict_mem_table_add_col(table, name, mtype, prtype, col_len,
  294. prec);
  295. btr_pcur_move_to_next_user_rec(&pcur, &mtr);
  296. btr_pcur_close(&pcur);
  297. mtr_commit(&mtr);
  298. }
  299. /************************************************************************
  300. Report that an index field or index for a table has been delete marked. */
  301. static
  302. void
  303. dict_load_report_deleted_index(
  304. /*===========================*/
  305. const char* name, /* in: table name */
  306. ulint field) /* in: index field, or ULINT_UNDEFINED */
  307. {
  308. fprintf(stderr, "InnoDB: Error: data dictionary entry"
  309. " for table %s is corrupt!n", name);
  310. if (field != ULINT_UNDEFINED) {
  311. fprintf(stderr,
  312. "InnoDB: Index field %lu is delete marked.n", field);
  313. } else {
  314. fputs("InnoDB: An index is delete marked.n", stderr);
  315. }
  316. }
  317. /************************************************************************
  318. Loads definitions for index fields. */
  319. static
  320. void
  321. dict_load_fields(
  322. /*=============*/
  323. dict_table_t* table, /* in: table */
  324. dict_index_t* index, /* in: index whose fields to load */
  325. mem_heap_t* heap) /* in: memory heap for temporary storage */
  326. {
  327. dict_table_t* sys_fields;
  328. dict_index_t* sys_index;
  329. btr_pcur_t pcur;
  330. dtuple_t* tuple;
  331. dfield_t* dfield;
  332. ulint pos_and_prefix_len;
  333. ulint prefix_len;
  334. rec_t* rec;
  335. byte* field;
  336. ulint len;
  337. byte* buf;
  338. ulint i;
  339. mtr_t mtr;
  340. #ifdef UNIV_SYNC_DEBUG
  341. ut_ad(mutex_own(&(dict_sys->mutex)));
  342. #endif /* UNIV_SYNC_DEBUG */
  343. UT_NOT_USED(table);
  344. mtr_start(&mtr);
  345. sys_fields = dict_table_get_low("SYS_FIELDS");
  346. sys_index = UT_LIST_GET_FIRST(sys_fields->indexes);
  347. tuple = dtuple_create(heap, 1);
  348. dfield = dtuple_get_nth_field(tuple, 0);
  349. buf = mem_heap_alloc(heap, 8);
  350. mach_write_to_8(buf, index->id);
  351. dfield_set_data(dfield, buf, 8);
  352. dict_index_copy_types(tuple, sys_index, 1);
  353. btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
  354. BTR_SEARCH_LEAF, &pcur, &mtr);
  355.     for (i = 0; i < index->n_fields; i++) {
  356. rec = btr_pcur_get_rec(&pcur);
  357. ut_a(btr_pcur_is_on_user_rec(&pcur, &mtr));
  358. if (rec_get_deleted_flag(rec)) {
  359. dict_load_report_deleted_index(table->name, i);
  360. }
  361. field = rec_get_nth_field(rec, 0, &len);
  362. ut_ad(len == 8);
  363. ut_a(ut_memcmp(buf, field, len) == 0);
  364. field = rec_get_nth_field(rec, 1, &len);
  365. ut_a(len == 4);
  366. /* The next field stores the field position in the index
  367. and a possible column prefix length if the index field
  368. does not contain the whole column. The storage format is
  369. like this: if there is at least one prefix field in the index,
  370. then the HIGH 2 bytes contain the field number (== i) and the
  371. low 2 bytes the prefix length for the field. Otherwise the
  372. field number (== i) is contained in the 2 LOW bytes. */
  373. pos_and_prefix_len = mach_read_from_4(field);
  374. ut_a((pos_and_prefix_len & 0xFFFFUL) == i
  375.      || (pos_and_prefix_len & 0xFFFF0000UL) == (i << 16));
  376. if ((i == 0 && pos_and_prefix_len > 0)
  377.     || (pos_and_prefix_len & 0xFFFF0000UL) > 0) {
  378.         prefix_len = pos_and_prefix_len & 0xFFFFUL;
  379. } else {
  380.         prefix_len = 0;
  381. }
  382. ut_a(0 == ut_strcmp("COL_NAME",
  383. dict_field_get_col(
  384. dict_index_get_nth_field(
  385. dict_table_get_first_index(sys_fields), 4))->name));
  386. field = rec_get_nth_field(rec, 4, &len);
  387. dict_mem_index_add_field(index,
  388.                                          mem_heap_strdupl(heap, (char*) field, len), 0, prefix_len);
  389. btr_pcur_move_to_next_user_rec(&pcur, &mtr);
  390. btr_pcur_close(&pcur);
  391. mtr_commit(&mtr);
  392. }
  393. /************************************************************************
  394. Loads definitions for table indexes. Adds them to the data dictionary
  395. cache. */
  396. static
  397. ibool
  398. dict_load_indexes(
  399. /*==============*/
  400. /* out: TRUE if ok, FALSE if corruption
  401. of dictionary table */
  402. dict_table_t* table, /* in: table */
  403. mem_heap_t* heap) /* in: memory heap for temporary storage */
  404. {
  405. dict_table_t* sys_indexes;
  406. dict_index_t* sys_index;
  407. dict_index_t* index;
  408. btr_pcur_t pcur;
  409. dtuple_t* tuple;
  410. dfield_t* dfield;
  411. rec_t* rec;
  412. byte* field;
  413. ulint len;
  414. ulint name_len;
  415. char* name_buf;
  416. ulint type;
  417. ulint space;
  418. ulint page_no;
  419. ulint n_fields;
  420. byte* buf;
  421. ibool is_sys_table;
  422. dulint id;
  423. mtr_t mtr;
  424. #ifdef UNIV_SYNC_DEBUG
  425. ut_ad(mutex_own(&(dict_sys->mutex)));
  426. #endif /* UNIV_SYNC_DEBUG */
  427. if ((ut_dulint_get_high(table->id) == 0)
  428.     && (ut_dulint_get_low(table->id) < DICT_HDR_FIRST_ID)) {
  429. is_sys_table = TRUE;
  430. } else {
  431. is_sys_table = FALSE;
  432. }
  433. mtr_start(&mtr);
  434. sys_indexes = dict_table_get_low("SYS_INDEXES");
  435. sys_index = UT_LIST_GET_FIRST(sys_indexes->indexes);
  436. tuple = dtuple_create(heap, 1);
  437. dfield = dtuple_get_nth_field(tuple, 0);
  438. buf = mem_heap_alloc(heap, 8);
  439. mach_write_to_8(buf, table->id);
  440. dfield_set_data(dfield, buf, 8);
  441. dict_index_copy_types(tuple, sys_index, 1);
  442. btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
  443. BTR_SEARCH_LEAF, &pcur, &mtr);
  444.     for (;;) {
  445. if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) {
  446. break;
  447. }
  448. rec = btr_pcur_get_rec(&pcur);
  449. field = rec_get_nth_field(rec, 0, &len);
  450. ut_ad(len == 8);
  451. if (ut_memcmp(buf, field, len) != 0) {
  452. break;
  453. }
  454. if (rec_get_deleted_flag(rec)) {
  455. dict_load_report_deleted_index(table->name,
  456. ULINT_UNDEFINED);
  457. btr_pcur_close(&pcur);
  458. mtr_commit(&mtr);
  459. return(FALSE);
  460. }
  461. field = rec_get_nth_field(rec, 1, &len);
  462. ut_ad(len == 8);
  463. id = mach_read_from_8(field);
  464. ut_a(0 == ut_strcmp("NAME",
  465. dict_field_get_col(
  466. dict_index_get_nth_field(
  467. dict_table_get_first_index(sys_indexes), 4))->name));
  468. field = rec_get_nth_field(rec, 4, &name_len);
  469. name_buf = mem_heap_strdupl(heap, (char*) field, name_len);
  470. field = rec_get_nth_field(rec, 5, &len);
  471. n_fields = mach_read_from_4(field);
  472. field = rec_get_nth_field(rec, 6, &len);
  473. type = mach_read_from_4(field);
  474. field = rec_get_nth_field(rec, 7, &len);
  475. space = mach_read_from_4(field);
  476. ut_a(0 == ut_strcmp("PAGE_NO",
  477. dict_field_get_col(
  478. dict_index_get_nth_field(
  479. dict_table_get_first_index(sys_indexes), 8))->name));
  480. field = rec_get_nth_field(rec, 8, &len);
  481. page_no = mach_read_from_4(field);
  482. if (page_no == FIL_NULL) {
  483. fprintf(stderr,
  484. "InnoDB: Error: trying to load index %s for table %sn"
  485. "InnoDB: but the index tree has been freed!n",
  486. name_buf, table->name);
  487. btr_pcur_close(&pcur);
  488. mtr_commit(&mtr);
  489. return(FALSE);
  490. }
  491. if ((type & DICT_CLUSTERED) == 0
  492.     && NULL == dict_table_get_first_index(table)) {
  493. fprintf(stderr,
  494. "InnoDB: Error: trying to load index %s for table %sn"
  495. "InnoDB: but the first index is not clustered!n",
  496. name_buf, table->name);
  497. btr_pcur_close(&pcur);
  498. mtr_commit(&mtr);
  499. return(FALSE);
  500. }
  501. if (is_sys_table
  502.     && ((type & DICT_CLUSTERED)
  503.         || ((table == dict_sys->sys_tables)
  504.             && (name_len == (sizeof "ID_IND") - 1)
  505.     && (0 == ut_memcmp(name_buf, "ID_IND",
  506. name_len))))) {
  507. /* The index was created in memory already at booting
  508. of the database server */
  509. } else {
  510.   index = dict_mem_index_create(table->name, name_buf,
  511. space, type, n_fields);
  512. index->page_no = page_no;
  513. index->id = id;
  514. dict_load_fields(table, index, heap);
  515. dict_index_add_to_cache(table, index);
  516. }
  517. btr_pcur_move_to_next_user_rec(&pcur, &mtr);
  518. btr_pcur_close(&pcur);
  519. mtr_commit(&mtr);
  520. return(TRUE);
  521. }
  522. /************************************************************************
  523. Loads a table definition and also all its index definitions, and also
  524. the cluster definition if the table is a member in a cluster. Also loads
  525. all foreign key constraints where the foreign key is in the table or where
  526. a foreign key references columns in this table. Adds all these to the data
  527. dictionary cache. */
  528. dict_table_t*
  529. dict_load_table(
  530. /*============*/
  531. /* out: table, NULL if does not exist;
  532. if the table is stored in an .ibd file,
  533. but the file does not exist,
  534. then we set the ibd_file_missing flag TRUE
  535. in the table object we return */
  536. const char* name) /* in: table name in the
  537. databasename/tablename format */
  538. {
  539. ibool ibd_file_missing = FALSE;
  540. dict_table_t* table;
  541. dict_table_t* sys_tables;
  542. btr_pcur_t pcur;
  543. dict_index_t* sys_index;
  544. dtuple_t* tuple;
  545. mem_heap_t* heap;
  546. dfield_t* dfield;
  547. rec_t* rec;
  548. byte* field;
  549. ulint len;
  550. ulint space;
  551. ulint n_cols;
  552. ulint err;
  553. mtr_t mtr;
  554. #ifdef UNIV_SYNC_DEBUG
  555. ut_ad(mutex_own(&(dict_sys->mutex)));
  556. #endif /* UNIV_SYNC_DEBUG */
  557. heap = mem_heap_create(1000);
  558. mtr_start(&mtr);
  559. sys_tables = dict_table_get_low("SYS_TABLES");
  560. sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
  561. tuple = dtuple_create(heap, 1);
  562. dfield = dtuple_get_nth_field(tuple, 0);
  563. dfield_set_data(dfield, name, ut_strlen(name));
  564. dict_index_copy_types(tuple, sys_index, 1);
  565. btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
  566. BTR_SEARCH_LEAF, &pcur, &mtr);
  567. rec = btr_pcur_get_rec(&pcur);
  568. if (!btr_pcur_is_on_user_rec(&pcur, &mtr)
  569. || rec_get_deleted_flag(rec)) {
  570. /* Not found */
  571. btr_pcur_close(&pcur);
  572. mtr_commit(&mtr);
  573. mem_heap_free(heap);
  574. return(NULL);
  575. }
  576. field = rec_get_nth_field(rec, 0, &len);
  577. /* Check if the table name in record is the searched one */
  578. if (len != ut_strlen(name) || ut_memcmp(name, field, len) != 0) {
  579. err_exit:
  580. btr_pcur_close(&pcur);
  581. mtr_commit(&mtr);
  582. mem_heap_free(heap);
  583. return(NULL);
  584. }
  585. ut_a(0 == ut_strcmp("SPACE",
  586. dict_field_get_col(
  587. dict_index_get_nth_field(
  588. dict_table_get_first_index(sys_tables), 9))->name));
  589. field = rec_get_nth_field(rec, 9, &len);
  590. space = mach_read_from_4(field);
  591. /* Check if the tablespace exists and has the right name */
  592. if (space != 0) {
  593. if (fil_space_for_table_exists_in_mem(space, name, FALSE,
  594. FALSE, FALSE)) {
  595. /* Ok; (if we did a crash recovery then the tablespace
  596. can already be in the memory cache) */
  597. } else {
  598. /* In >= 4.1.9, InnoDB scans the data dictionary also
  599. at a normal mysqld startup. It is an error if the
  600. space object does not exist in memory. */
  601. ut_print_timestamp(stderr);
  602. fprintf(stderr,
  603. "  InnoDB: error: space object of table %s,n"
  604. "InnoDB: space id %lu did not exist in memory. Retrying an open.n",
  605. name, (ulong)space);
  606. /* Try to open the tablespace */
  607. if (!fil_open_single_table_tablespace(TRUE,
  608. space, name)) {
  609. /* We failed to find a sensible tablespace
  610. file */
  611. ibd_file_missing = TRUE;
  612. }
  613. }
  614. }
  615. ut_a(0 == ut_strcmp("N_COLS",
  616. dict_field_get_col(
  617. dict_index_get_nth_field(
  618. dict_table_get_first_index(sys_tables), 4))->name));
  619. field = rec_get_nth_field(rec, 4, &len);
  620. n_cols = mach_read_from_4(field);
  621. if (n_cols & 0x80000000UL) {
  622. ut_print_timestamp(stderr);
  623. fprintf(stderr,
  624. "  InnoDB: table %s is in the new compact formatn"
  625. "InnoDB: of MySQL 5.0.3 or latern", name);
  626. goto err_exit;
  627. }
  628. table = dict_mem_table_create(name, space, n_cols);
  629. table->ibd_file_missing = ibd_file_missing;
  630. ut_a(0 == ut_strcmp("ID",
  631. dict_field_get_col(
  632. dict_index_get_nth_field(
  633. dict_table_get_first_index(sys_tables), 3))->name));
  634. field = rec_get_nth_field(rec, 3, &len);
  635. table->id = mach_read_from_8(field);
  636. field = rec_get_nth_field(rec, 5, &len);
  637. table->type = mach_read_from_4(field);
  638. if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
  639. ut_error;
  640. #if 0 /* clustered tables have not been implemented yet */
  641. field = rec_get_nth_field(rec, 6, &len);
  642. table->mix_id = mach_read_from_8(field);
  643. field = rec_get_nth_field(rec, 8, &len);
  644. table->cluster_name = mem_heap_strdupl(heap, (char*) field, len);
  645. #endif
  646. }
  647. if ((table->type == DICT_TABLE_CLUSTER)
  648.     || (table->type == DICT_TABLE_CLUSTER_MEMBER)) {
  649. field = rec_get_nth_field(rec, 7, &len);
  650. table->mix_len = mach_read_from_4(field);
  651. }
  652. btr_pcur_close(&pcur);
  653. mtr_commit(&mtr);
  654. if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
  655. /* Load the cluster table definition if not yet in
  656. memory cache */
  657. dict_table_get_low(table->cluster_name);
  658. }
  659. dict_load_columns(table, heap);
  660. dict_table_add_to_cache(table);
  661. dict_load_indexes(table, heap);
  662. err = dict_load_foreigns(table->name, TRUE);
  663. /*
  664. if (err != DB_SUCCESS) {
  665.   mutex_enter(&dict_foreign_err_mutex);
  666.   ut_print_timestamp(stderr);
  667.  
  668. fprintf(stderr,
  669. "  InnoDB: Error: could not make a foreign key definition to matchn"
  670. "InnoDB: the foreign key table or the referenced table!n"
  671. "InnoDB: The data dictionary of InnoDB is corrupt. You may need to dropn"
  672. "InnoDB: and recreate the foreign key table or the referenced table.n"
  673. "InnoDB: Submit a detailed bug report to http://bugs.mysql.comn"
  674. "InnoDB: Latest foreign key error printout:n%sn", dict_foreign_err_buf);
  675. mutex_exit(&dict_foreign_err_mutex);
  676. }
  677. */
  678. mem_heap_free(heap);
  679. return(table);
  680. }
  681. /***************************************************************************
  682. Loads a table object based on the table id. */
  683. dict_table_t*
  684. dict_load_table_on_id(
  685. /*==================*/
  686. /* out: table; NULL if table does not exist */
  687. dulint table_id) /* in: table id */
  688. {
  689. byte id_buf[8];
  690. btr_pcur_t pcur;
  691. mem_heap_t*  heap;
  692. dtuple_t* tuple;
  693. dfield_t* dfield;
  694. dict_index_t* sys_table_ids;
  695. dict_table_t* sys_tables;
  696. rec_t* rec;
  697. byte* field;
  698. ulint len;
  699. dict_table_t* table;
  700. mtr_t mtr;
  701. #ifdef UNIV_SYNC_DEBUG
  702. ut_ad(mutex_own(&(dict_sys->mutex)));
  703. #endif /* UNIV_SYNC_DEBUG */
  704. /* NOTE that the operation of this function is protected by
  705. the dictionary mutex, and therefore no deadlocks can occur
  706. with other dictionary operations. */
  707. mtr_start(&mtr);
  708. /*---------------------------------------------------*/
  709. /* Get the secondary index based on ID for table SYS_TABLES */
  710. sys_tables = dict_sys->sys_tables;
  711. sys_table_ids = dict_table_get_next_index(
  712. dict_table_get_first_index(sys_tables));
  713. heap = mem_heap_create(256);
  714. tuple  = dtuple_create(heap, 1);
  715. dfield = dtuple_get_nth_field(tuple, 0);
  716. /* Write the table id in byte format to id_buf */
  717. mach_write_to_8(id_buf, table_id);
  718. dfield_set_data(dfield, id_buf, 8);
  719. dict_index_copy_types(tuple, sys_table_ids, 1);
  720. btr_pcur_open_on_user_rec(sys_table_ids, tuple, PAGE_CUR_GE,
  721. BTR_SEARCH_LEAF, &pcur, &mtr);
  722. rec = btr_pcur_get_rec(&pcur);
  723. if (!btr_pcur_is_on_user_rec(&pcur, &mtr)
  724. || rec_get_deleted_flag(rec)) {
  725. /* Not found */
  726. btr_pcur_close(&pcur);
  727. mtr_commit(&mtr);
  728. mem_heap_free(heap);
  729. return(NULL);
  730. }
  731. /*---------------------------------------------------*/
  732. /* Now we have the record in the secondary index containing the
  733. table ID and NAME */
  734. rec = btr_pcur_get_rec(&pcur);
  735. field = rec_get_nth_field(rec, 0, &len);
  736. ut_ad(len == 8);
  737. /* Check if the table id in record is the one searched for */
  738. if (ut_dulint_cmp(table_id, mach_read_from_8(field)) != 0) {
  739. btr_pcur_close(&pcur);
  740. mtr_commit(&mtr);
  741. mem_heap_free(heap);
  742. return(NULL);
  743. }
  744. /* Now we get the table name from the record */
  745. field = rec_get_nth_field(rec, 1, &len);
  746. /* Load the table definition to memory */
  747. table = dict_load_table(mem_heap_strdupl(heap, (char*) field, len));
  748. btr_pcur_close(&pcur);
  749. mtr_commit(&mtr);
  750. mem_heap_free(heap);
  751. return(table);
  752. }
  753. /************************************************************************
  754. This function is called when the database is booted. Loads system table
  755. index definitions except for the clustered index which is added to the
  756. dictionary cache at booting before calling this function. */
  757. void
  758. dict_load_sys_table(
  759. /*================*/
  760. dict_table_t* table) /* in: system table */
  761. {
  762. mem_heap_t* heap;
  763. #ifdef UNIV_SYNC_DEBUG
  764. ut_ad(mutex_own(&(dict_sys->mutex)));
  765. #endif /* UNIV_SYNC_DEBUG */
  766. heap = mem_heap_create(1000);
  767. dict_load_indexes(table, heap);
  768. mem_heap_free(heap);
  769. }
  770. /************************************************************************
  771. Loads foreign key constraint col names (also for the referenced table). */
  772. static
  773. void
  774. dict_load_foreign_cols(
  775. /*===================*/
  776. const char* id, /* in: foreign constraint id as a null-
  777. terminated string */
  778. dict_foreign_t* foreign)/* in: foreign constraint object */
  779. {
  780. dict_table_t* sys_foreign_cols;
  781. dict_index_t* sys_index;
  782. btr_pcur_t pcur;
  783. dtuple_t* tuple;
  784. dfield_t* dfield;
  785. rec_t* rec;
  786. byte* field;
  787. ulint len;
  788. ulint i;
  789. mtr_t mtr;
  790. #ifdef UNIV_SYNC_DEBUG
  791. ut_ad(mutex_own(&(dict_sys->mutex)));
  792. #endif /* UNIV_SYNC_DEBUG */
  793. foreign->foreign_col_names = mem_heap_alloc(foreign->heap,
  794. foreign->n_fields * sizeof(void*));
  795. foreign->referenced_col_names = mem_heap_alloc(foreign->heap,
  796. foreign->n_fields * sizeof(void*));
  797. mtr_start(&mtr);
  798. sys_foreign_cols = dict_table_get_low("SYS_FOREIGN_COLS");
  799. sys_index = UT_LIST_GET_FIRST(sys_foreign_cols->indexes);
  800. tuple = dtuple_create(foreign->heap, 1);
  801. dfield = dtuple_get_nth_field(tuple, 0);
  802. dfield_set_data(dfield, id, ut_strlen(id));
  803. dict_index_copy_types(tuple, sys_index, 1);
  804. btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
  805. BTR_SEARCH_LEAF, &pcur, &mtr);
  806.     for (i = 0; i < foreign->n_fields; i++) {
  807. rec = btr_pcur_get_rec(&pcur);
  808. ut_a(btr_pcur_is_on_user_rec(&pcur, &mtr));
  809. ut_a(!rec_get_deleted_flag(rec));
  810. field = rec_get_nth_field(rec, 0, &len);
  811. ut_a(len == ut_strlen(id));
  812. ut_a(ut_memcmp(id, field, len) == 0);
  813. field = rec_get_nth_field(rec, 1, &len);
  814. ut_a(len == 4);
  815. ut_a(i == mach_read_from_4(field));
  816. field = rec_get_nth_field(rec, 4, &len);
  817. foreign->foreign_col_names[i] =
  818.                         mem_heap_strdupl(foreign->heap, (char*) field, len);
  819. field = rec_get_nth_field(rec, 5, &len);
  820. foreign->referenced_col_names[i] =
  821.                   mem_heap_strdupl(foreign->heap, (char*) field, len);
  822. btr_pcur_move_to_next_user_rec(&pcur, &mtr);
  823. btr_pcur_close(&pcur);
  824. mtr_commit(&mtr);
  825. }
  826. /***************************************************************************
  827. Loads a foreign key constraint to the dictionary cache. */
  828. static
  829. ulint
  830. dict_load_foreign(
  831. /*==============*/
  832. /* out: DB_SUCCESS or error code */
  833. const char* id, /* in: foreign constraint id as a
  834. null-terminated string */
  835. ibool check_types)/* in: TRUE=check type compatibility */
  836. {
  837. dict_foreign_t* foreign;
  838. dict_table_t* sys_foreign;
  839. btr_pcur_t pcur;
  840. dict_index_t* sys_index;
  841. dtuple_t* tuple;
  842. mem_heap_t* heap2;
  843. dfield_t* dfield;
  844. rec_t* rec;
  845. byte* field;
  846. ulint len;
  847. mtr_t mtr;
  848. #ifdef UNIV_SYNC_DEBUG
  849. ut_ad(mutex_own(&(dict_sys->mutex)));
  850. #endif /* UNIV_SYNC_DEBUG */
  851. heap2 = mem_heap_create(1000);
  852. mtr_start(&mtr);
  853. sys_foreign = dict_table_get_low("SYS_FOREIGN");
  854. sys_index = UT_LIST_GET_FIRST(sys_foreign->indexes);
  855. tuple = dtuple_create(heap2, 1);
  856. dfield = dtuple_get_nth_field(tuple, 0);
  857. dfield_set_data(dfield, id, ut_strlen(id));
  858. dict_index_copy_types(tuple, sys_index, 1);
  859. btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
  860. BTR_SEARCH_LEAF, &pcur, &mtr);
  861. rec = btr_pcur_get_rec(&pcur);
  862. if (!btr_pcur_is_on_user_rec(&pcur, &mtr)
  863. || rec_get_deleted_flag(rec)) {
  864. /* Not found */
  865. fprintf(stderr,
  866. "InnoDB: Error A: cannot load foreign constraint %sn",
  867. id);
  868. btr_pcur_close(&pcur);
  869. mtr_commit(&mtr);
  870. mem_heap_free(heap2);
  871. return(DB_ERROR);
  872. }
  873. field = rec_get_nth_field(rec, 0, &len);
  874. /* Check if the id in record is the searched one */
  875. if (len != ut_strlen(id) || ut_memcmp(id, field, len) != 0) {
  876. fprintf(stderr,
  877. "InnoDB: Error B: cannot load foreign constraint %sn",
  878. id);
  879. btr_pcur_close(&pcur);
  880. mtr_commit(&mtr);
  881. mem_heap_free(heap2);
  882. return(DB_ERROR);
  883. }
  884. /* Read the table names and the number of columns associated
  885. with the constraint */
  886. mem_heap_free(heap2);
  887. foreign = dict_mem_foreign_create();
  888. foreign->n_fields = mach_read_from_4(rec_get_nth_field(rec, 5, &len));
  889. ut_a(len == 4);
  890. /* We store the type to the bits 24-31 of n_fields */
  891. foreign->type = foreign->n_fields >> 24;
  892. foreign->n_fields = foreign->n_fields & 0xFFFFFFUL;
  893. foreign->id = mem_heap_strdup(foreign->heap, id);
  894. field = rec_get_nth_field(rec, 3, &len);
  895. foreign->foreign_table_name =
  896.                 mem_heap_strdupl(foreign->heap, (char*) field, len);
  897. field = rec_get_nth_field(rec, 4, &len);
  898. foreign->referenced_table_name =
  899.                 mem_heap_strdupl(foreign->heap, (char*) field, len);
  900. btr_pcur_close(&pcur);
  901. mtr_commit(&mtr);
  902. dict_load_foreign_cols(id, foreign);
  903. /* If the foreign table is not yet in the dictionary cache, we
  904. have to load it so that we are able to make type comparisons
  905. in the next function call. */
  906. dict_table_get_low(foreign->foreign_table_name);
  907. /* Note that there may already be a foreign constraint object in
  908. the dictionary cache for this constraint: then the following
  909. call only sets the pointers in it to point to the appropriate table
  910. and index objects and frees the newly created object foreign.
  911. Adding to the cache should always succeed since we are not creating
  912. a new foreign key constraint but loading one from the data
  913. dictionary. */
  914. return(dict_foreign_add_to_cache(foreign, check_types));
  915. }
  916. /***************************************************************************
  917. Loads foreign key constraints where the table is either the foreign key
  918. holder or where the table is referenced by a foreign key. Adds these
  919. constraints to the data dictionary. Note that we know that the dictionary
  920. cache already contains all constraints where the other relevant table is
  921. already in the dictionary cache. */
  922. ulint
  923. dict_load_foreigns(
  924. /*===============*/
  925. /* out: DB_SUCCESS or error code */
  926. const char* table_name, /* in: table name */
  927. ibool check_types) /* in: TRUE=check type compatibility */
  928. {
  929. btr_pcur_t pcur;
  930. mem_heap_t*  heap;
  931. dtuple_t* tuple;
  932. dfield_t* dfield;
  933. dict_index_t* sec_index;
  934. dict_table_t* sys_foreign;
  935. rec_t* rec;
  936. byte* field;
  937. ulint len;
  938. char* id ;
  939. ulint err;
  940. mtr_t mtr;
  941. #ifdef UNIV_SYNC_DEBUG
  942. ut_ad(mutex_own(&(dict_sys->mutex)));
  943. #endif /* UNIV_SYNC_DEBUG */
  944. sys_foreign = dict_table_get_low("SYS_FOREIGN");
  945. if (sys_foreign == NULL) {
  946. /* No foreign keys defined yet in this database */
  947. fprintf(stderr,
  948. "InnoDB: Error: no foreign key system tables in the databasen");
  949. return(DB_ERROR);
  950. }
  951. mtr_start(&mtr);
  952. /* Get the secondary index based on FOR_NAME from table
  953. SYS_FOREIGN */
  954. sec_index = dict_table_get_next_index(
  955. dict_table_get_first_index(sys_foreign));
  956. start_load:
  957. heap = mem_heap_create(256);
  958. tuple  = dtuple_create(heap, 1);
  959. dfield = dtuple_get_nth_field(tuple, 0);
  960. dfield_set_data(dfield, table_name, ut_strlen(table_name));
  961. dict_index_copy_types(tuple, sec_index, 1);
  962. btr_pcur_open_on_user_rec(sec_index, tuple, PAGE_CUR_GE,
  963. BTR_SEARCH_LEAF, &pcur, &mtr);
  964. loop:
  965. rec = btr_pcur_get_rec(&pcur);
  966. if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) {
  967. /* End of index */
  968. goto load_next_index;
  969. }
  970. /* Now we have the record in the secondary index containing a table
  971. name and a foreign constraint ID */
  972. rec = btr_pcur_get_rec(&pcur);
  973. field = rec_get_nth_field(rec, 0, &len);
  974. /* Check if the table name in the record is the one searched for; the
  975. following call does the comparison in the latin1_swedish_ci
  976. charset-collation, in a case-insensitive way. */
  977. if (0 != cmp_data_data(dfield_get_type(dfield),
  978. dfield_get_data(dfield), dfield_get_len(dfield),
  979. field, len)) {
  980. goto load_next_index;
  981. }
  982. /* Since table names in SYS_FOREIGN are stored in a case-insensitive
  983. order, we have to check that the table name matches also in a binary
  984. string comparison. On Unix, MySQL allows table names that only differ
  985. in character case. */
  986. if (0 != ut_memcmp(field, table_name, len)) {
  987. goto next_rec;
  988. }
  989. if (rec_get_deleted_flag(rec)) {
  990. goto next_rec;
  991. }
  992. /* Now we get a foreign key constraint id */
  993. field = rec_get_nth_field(rec, 1, &len);
  994. id = mem_heap_strdupl(heap, (char*) field, len);
  995. btr_pcur_store_position(&pcur, &mtr);
  996. mtr_commit(&mtr);
  997. /* Load the foreign constraint definition to the dictionary cache */
  998. err = dict_load_foreign(id, check_types);
  999. if (err != DB_SUCCESS) {
  1000. btr_pcur_close(&pcur);
  1001. mem_heap_free(heap);
  1002. return(err);
  1003. }
  1004. mtr_start(&mtr);
  1005. btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
  1006. next_rec:
  1007. btr_pcur_move_to_next_user_rec(&pcur, &mtr);
  1008. goto loop;
  1009. load_next_index:
  1010. btr_pcur_close(&pcur);
  1011. mtr_commit(&mtr);
  1012. mem_heap_free(heap);
  1013. sec_index = dict_table_get_next_index(sec_index);
  1014. if (sec_index != NULL) {
  1015. mtr_start(&mtr);
  1016. goto start_load;
  1017. }
  1018. return(DB_SUCCESS);
  1019. }