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

MySQL数据库

开发平台:

Visual C++

  1. /******************************************************
  2. Database object creation
  3. (c) 1996 Innobase Oy
  4. Created 1/8/1996 Heikki Tuuri
  5. *******************************************************/
  6. #include "dict0crea.h"
  7. #ifdef UNIV_NONINL
  8. #include "dict0crea.ic"
  9. #endif
  10. #include "btr0pcur.h"
  11. #include "btr0btr.h"
  12. #include "page0page.h"
  13. #include "mach0data.h"
  14. #include "dict0boot.h"
  15. #include "dict0dict.h"
  16. #include "que0que.h"
  17. #include "row0ins.h"
  18. #include "row0mysql.h"
  19. #include "pars0pars.h"
  20. #include "trx0roll.h"
  21. #include "usr0sess.h"
  22. /*********************************************************************
  23. Based on a table object, this function builds the entry to be inserted
  24. in the SYS_TABLES system table. */
  25. static
  26. dtuple_t*
  27. dict_create_sys_tables_tuple(
  28. /*=========================*/
  29. /* out: the tuple which should be inserted */
  30. dict_table_t* table,  /* in: table */
  31. mem_heap_t* heap) /* in: memory heap from which the memory for
  32. the built tuple is allocated */
  33. {
  34. dict_table_t* sys_tables;
  35. dtuple_t* entry;
  36. dfield_t* dfield;
  37. byte* ptr;
  38. ut_ad(table && heap);
  39. sys_tables = dict_sys->sys_tables;
  40. entry = dtuple_create(heap, 8 + DATA_N_SYS_COLS);
  41. /* 0: NAME -----------------------------*/
  42. dfield = dtuple_get_nth_field(entry, 0);
  43. dfield_set_data(dfield, table->name, ut_strlen(table->name));
  44. /* 3: ID -------------------------------*/
  45. dfield = dtuple_get_nth_field(entry, 1);
  46. ptr = mem_heap_alloc(heap, 8);
  47. mach_write_to_8(ptr, table->id);
  48. dfield_set_data(dfield, ptr, 8);
  49. /* 4: N_COLS ---------------------------*/
  50. dfield = dtuple_get_nth_field(entry, 2);
  51. ptr = mem_heap_alloc(heap, 4);
  52. mach_write_to_4(ptr, table->n_def);
  53. dfield_set_data(dfield, ptr, 4);
  54. /* 5: TYPE -----------------------------*/
  55. dfield = dtuple_get_nth_field(entry, 3);
  56. ptr = mem_heap_alloc(heap, 4);
  57. mach_write_to_4(ptr, table->type);
  58. dfield_set_data(dfield, ptr, 4);
  59. /* 6: MIX_ID ---------------------------*/
  60. dfield = dtuple_get_nth_field(entry, 4);
  61. ptr = mem_heap_alloc(heap, 8);
  62. mach_write_to_8(ptr, table->mix_id);
  63. dfield_set_data(dfield, ptr, 8);
  64. /* 7: MIX_LEN --------------------------*/
  65. /* Track corruption reported on mailing list Jan 14, 2005 */
  66. if (table->mix_len != 0 && table->mix_len != 0x80000000) {
  67. fprintf(stderr,
  68. "InnoDB: Error: mix_len is %lu in table %sn", (ulong)table->mix_len,
  69. table->name);
  70. mem_analyze_corruption((byte*)&(table->mix_len));
  71. ut_error;
  72. }
  73. dfield = dtuple_get_nth_field(entry, 5);
  74. ptr = mem_heap_alloc(heap, 4);
  75. mach_write_to_4(ptr, table->mix_len);
  76. dfield_set_data(dfield, ptr, 4);
  77. /* 8: CLUSTER_NAME ---------------------*/
  78. dfield = dtuple_get_nth_field(entry, 6);
  79.   if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
  80. dfield_set_data(dfield, table->cluster_name,
  81. ut_strlen(table->cluster_name));
  82. ut_error; /* Oracle-style clusters are not supported yet */
  83. } else {
  84. dfield_set_data(dfield, NULL, UNIV_SQL_NULL);
  85. }
  86. /* 9: SPACE ----------------------------*/
  87. dfield = dtuple_get_nth_field(entry, 7);
  88. ptr = mem_heap_alloc(heap, 4);
  89. mach_write_to_4(ptr, table->space);
  90. dfield_set_data(dfield, ptr, 4);
  91. /*----------------------------------*/
  92. dict_table_copy_types(entry, sys_tables);
  93. return(entry);
  94. }
  95. /*********************************************************************
  96. Based on a table object, this function builds the entry to be inserted
  97. in the SYS_COLUMNS system table. */
  98. static
  99. dtuple_t*
  100. dict_create_sys_columns_tuple(
  101. /*==========================*/
  102. /* out: the tuple which should be inserted */
  103. dict_table_t* table,  /* in: table */
  104. ulint i, /* in: column number */
  105. mem_heap_t* heap) /* in: memory heap from which the memory for
  106. the built tuple is allocated */
  107. {
  108. dict_table_t* sys_columns;
  109. dtuple_t* entry;
  110. dict_col_t* column;
  111. dfield_t* dfield;
  112. byte* ptr;
  113. ut_ad(table && heap);
  114. column = dict_table_get_nth_col(table, i);
  115. sys_columns = dict_sys->sys_columns;
  116. entry = dtuple_create(heap, 7 + DATA_N_SYS_COLS);
  117. /* 0: TABLE_ID -----------------------*/
  118. dfield = dtuple_get_nth_field(entry, 0);
  119. ptr = mem_heap_alloc(heap, 8);
  120. mach_write_to_8(ptr, table->id);
  121. dfield_set_data(dfield, ptr, 8);
  122. /* 1: POS ----------------------------*/
  123. dfield = dtuple_get_nth_field(entry, 1);
  124. ptr = mem_heap_alloc(heap, 4);
  125. mach_write_to_4(ptr, i);
  126. dfield_set_data(dfield, ptr, 4);
  127. /* 4: NAME ---------------------------*/
  128. dfield = dtuple_get_nth_field(entry, 2);
  129. dfield_set_data(dfield, column->name, ut_strlen(column->name));
  130. /* 5: MTYPE --------------------------*/
  131. dfield = dtuple_get_nth_field(entry, 3);
  132. ptr = mem_heap_alloc(heap, 4);
  133. mach_write_to_4(ptr, (column->type).mtype);
  134. dfield_set_data(dfield, ptr, 4);
  135. /* 6: PRTYPE -------------------------*/
  136. dfield = dtuple_get_nth_field(entry, 4);
  137. ptr = mem_heap_alloc(heap, 4);
  138. mach_write_to_4(ptr, (column->type).prtype);
  139. dfield_set_data(dfield, ptr, 4);
  140. /* 7: LEN ----------------------------*/
  141. dfield = dtuple_get_nth_field(entry, 5);
  142. ptr = mem_heap_alloc(heap, 4);
  143. mach_write_to_4(ptr, (column->type).len);
  144. dfield_set_data(dfield, ptr, 4);
  145. /* 8: PREC ---------------------------*/
  146. dfield = dtuple_get_nth_field(entry, 6);
  147. ptr = mem_heap_alloc(heap, 4);
  148. mach_write_to_4(ptr, (column->type).prec);
  149. dfield_set_data(dfield, ptr, 4);
  150. /*---------------------------------*/
  151. dict_table_copy_types(entry, sys_columns);
  152. return(entry);
  153. }
  154. /*******************************************************************
  155. Builds a table definition to insert. */
  156. static
  157. ulint
  158. dict_build_table_def_step(
  159. /*======================*/
  160. /* out: DB_SUCCESS or error code */
  161. que_thr_t* thr, /* in: query thread */
  162. tab_node_t* node) /* in: table create node */
  163. {
  164. dict_table_t* table;
  165. dict_table_t* cluster_table;
  166. dtuple_t* row;
  167. ulint error;
  168. const char* path_or_name;
  169. ibool is_path;
  170. mtr_t mtr;
  171. #ifdef UNIV_SYNC_DEBUG
  172. ut_ad(mutex_own(&(dict_sys->mutex)));
  173. #endif /* UNIV_SYNC_DEBUG */
  174. table = node->table;
  175. table->id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID);
  176. thr_get_trx(thr)->table_id = table->id;
  177. if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
  178. cluster_table = dict_table_get_low(table->cluster_name);
  179. if (cluster_table == NULL) {
  180. return(DB_CLUSTER_NOT_FOUND);
  181. }
  182. /* Inherit space and mix len from the cluster */
  183. table->space = cluster_table->space;
  184. table->mix_len = cluster_table->mix_len;
  185. table->mix_id = dict_hdr_get_new_id(DICT_HDR_MIX_ID);
  186. }
  187. if (srv_file_per_table) {
  188. /* We create a new single-table tablespace for the table.
  189. We initially let it be 4 pages:
  190. - page 0 is the fsp header and an extent descriptor page,
  191. - page 1 is an ibuf bitmap page,
  192. - page 2 is the first inode page,
  193. - page 3 will contain the root of the clustered index of the
  194.   table we create here. */
  195. table->space = 0; /* reset to zero for the call below */
  196. if (table->dir_path_of_temp_table) {
  197. /* We place tables created with CREATE TEMPORARY
  198. TABLE in the tmp dir of mysqld server */
  199. path_or_name = table->dir_path_of_temp_table;
  200. is_path = TRUE;
  201. } else {
  202. path_or_name = table->name;
  203. is_path = FALSE;
  204. }
  205. error = fil_create_new_single_table_tablespace(
  206. &(table->space), path_or_name, is_path,
  207. FIL_IBD_FILE_INITIAL_SIZE);
  208. if (error != DB_SUCCESS) {
  209. return(error);
  210. }
  211. mtr_start(&mtr);
  212. fsp_header_init(table->space, FIL_IBD_FILE_INITIAL_SIZE, &mtr);
  213. mtr_commit(&mtr);
  214. }
  215. row = dict_create_sys_tables_tuple(table, node->heap);
  216. ins_node_set_new_row(node->tab_def, row);
  217. return(DB_SUCCESS);
  218. }
  219. /*******************************************************************
  220. Builds a column definition to insert. */
  221. static
  222. ulint
  223. dict_build_col_def_step(
  224. /*====================*/
  225. /* out: DB_SUCCESS */
  226. tab_node_t* node) /* in: table create node */
  227. {
  228. dtuple_t* row;
  229. row = dict_create_sys_columns_tuple(node->table, node->col_no,
  230. node->heap);
  231. ins_node_set_new_row(node->col_def, row);
  232. return(DB_SUCCESS);
  233. }
  234. /*********************************************************************
  235. Based on an index object, this function builds the entry to be inserted
  236. in the SYS_INDEXES system table. */
  237. static
  238. dtuple_t*
  239. dict_create_sys_indexes_tuple(
  240. /*==========================*/
  241. /* out: the tuple which should be inserted */
  242. dict_index_t* index,  /* in: index */
  243. mem_heap_t* heap) /* in: memory heap from which the memory for
  244. the built tuple is allocated */
  245. {
  246. dict_table_t* sys_indexes;
  247. dict_table_t* table;
  248. dtuple_t* entry;
  249. dfield_t* dfield;
  250. byte* ptr;
  251. #ifdef UNIV_SYNC_DEBUG
  252. ut_ad(mutex_own(&(dict_sys->mutex)));
  253. #endif /* UNIV_SYNC_DEBUG */
  254. ut_ad(index && heap);
  255. sys_indexes = dict_sys->sys_indexes;
  256. table = dict_table_get_low(index->table_name);
  257. entry = dtuple_create(heap, 7 + DATA_N_SYS_COLS);
  258. /* 0: TABLE_ID -----------------------*/
  259. dfield = dtuple_get_nth_field(entry, 0);
  260. ptr = mem_heap_alloc(heap, 8);
  261. mach_write_to_8(ptr, table->id);
  262. dfield_set_data(dfield, ptr, 8);
  263. /* 1: ID ----------------------------*/
  264. dfield = dtuple_get_nth_field(entry, 1);
  265. ptr = mem_heap_alloc(heap, 8);
  266. mach_write_to_8(ptr, index->id);
  267. dfield_set_data(dfield, ptr, 8);
  268. /* 4: NAME --------------------------*/
  269. dfield = dtuple_get_nth_field(entry, 2);
  270. dfield_set_data(dfield, index->name, ut_strlen(index->name));
  271. /* 5: N_FIELDS ----------------------*/
  272. dfield = dtuple_get_nth_field(entry, 3);
  273. ptr = mem_heap_alloc(heap, 4);
  274. mach_write_to_4(ptr, index->n_fields);
  275. dfield_set_data(dfield, ptr, 4);
  276. /* 6: TYPE --------------------------*/
  277. dfield = dtuple_get_nth_field(entry, 4);
  278. ptr = mem_heap_alloc(heap, 4);
  279. mach_write_to_4(ptr, index->type);
  280. dfield_set_data(dfield, ptr, 4);
  281. /* 7: SPACE --------------------------*/
  282. #if DICT_SYS_INDEXES_SPACE_NO_FIELD != 7
  283. #error "DICT_SYS_INDEXES_SPACE_NO_FIELD != 7"
  284. #endif
  285. dfield = dtuple_get_nth_field(entry, 5);
  286. ptr = mem_heap_alloc(heap, 4);
  287. mach_write_to_4(ptr, index->space);
  288. dfield_set_data(dfield, ptr, 4);
  289. /* 8: PAGE_NO --------------------------*/
  290. #if DICT_SYS_INDEXES_PAGE_NO_FIELD != 8
  291. #error "DICT_SYS_INDEXES_PAGE_NO_FIELD != 8"
  292. #endif
  293. dfield = dtuple_get_nth_field(entry, 6);
  294. ptr = mem_heap_alloc(heap, 4);
  295. mach_write_to_4(ptr, FIL_NULL);
  296. dfield_set_data(dfield, ptr, 4);
  297. /*--------------------------------*/
  298. dict_table_copy_types(entry, sys_indexes);
  299. return(entry);
  300. }
  301. /*********************************************************************
  302. Based on an index object, this function builds the entry to be inserted
  303. in the SYS_FIELDS system table. */
  304. static
  305. dtuple_t*
  306. dict_create_sys_fields_tuple(
  307. /*=========================*/
  308. /* out: the tuple which should be inserted */
  309. dict_index_t* index,  /* in: index */
  310. ulint i, /* in: field number */
  311. mem_heap_t* heap) /* in: memory heap from which the memory for
  312. the built tuple is allocated */
  313. {
  314. dict_table_t* sys_fields;
  315. dtuple_t* entry;
  316. dict_field_t* field;
  317. dfield_t* dfield;
  318. byte* ptr;
  319. ibool index_contains_column_prefix_field = FALSE;
  320. ulint j;
  321. ut_ad(index && heap);
  322. for (j = 0; j < index->n_fields; j++) {
  323.         if (dict_index_get_nth_field(index, j)->prefix_len > 0) {
  324.                 index_contains_column_prefix_field = TRUE;    
  325. }
  326. }
  327. field = dict_index_get_nth_field(index, i);
  328. sys_fields = dict_sys->sys_fields;
  329. entry = dtuple_create(heap, 3 + DATA_N_SYS_COLS);
  330. /* 0: INDEX_ID -----------------------*/
  331. dfield = dtuple_get_nth_field(entry, 0);
  332. ptr = mem_heap_alloc(heap, 8);
  333. mach_write_to_8(ptr, index->id);
  334. dfield_set_data(dfield, ptr, 8);
  335. /* 1: POS + PREFIX LENGTH ----------------------------*/
  336. dfield = dtuple_get_nth_field(entry, 1);
  337. ptr = mem_heap_alloc(heap, 4);
  338. if (index_contains_column_prefix_field) {
  339. /* If there are column prefix fields in the index, then
  340. we store the number of the field to the 2 HIGH bytes
  341. and the prefix length to the 2 low bytes, */
  342.         mach_write_to_4(ptr, (i << 16) + field->prefix_len);
  343. } else {
  344.         /* Else we store the number of the field to the 2 LOW bytes.
  345. This is to keep the storage format compatible with
  346. InnoDB versions < 4.0.14. */
  347.   
  348.         mach_write_to_4(ptr, i);
  349. }
  350. dfield_set_data(dfield, ptr, 4);
  351. /* 4: COL_NAME -------------------------*/
  352. dfield = dtuple_get_nth_field(entry, 2);
  353. dfield_set_data(dfield, field->name,
  354. ut_strlen(field->name));
  355. /*---------------------------------*/
  356. dict_table_copy_types(entry, sys_fields);
  357. return(entry);
  358. }
  359. /*********************************************************************
  360. Creates the tuple with which the index entry is searched for writing the index
  361. tree root page number, if such a tree is created. */
  362. static
  363. dtuple_t*
  364. dict_create_search_tuple(
  365. /*=====================*/
  366. /* out: the tuple for search */
  367. dtuple_t* tuple, /* in: the tuple inserted in the SYS_INDEXES
  368. table */
  369. mem_heap_t* heap) /* in: memory heap from which the memory for
  370. the built tuple is allocated */
  371. {
  372. dtuple_t* search_tuple;
  373. dfield_t* field1;
  374. dfield_t* field2;
  375. ut_ad(tuple && heap);
  376. search_tuple = dtuple_create(heap, 2);
  377. field1 = dtuple_get_nth_field(tuple, 0);
  378. field2 = dtuple_get_nth_field(search_tuple, 0);
  379. dfield_copy(field2, field1);
  380. field1 = dtuple_get_nth_field(tuple, 1);
  381. field2 = dtuple_get_nth_field(search_tuple, 1);
  382. dfield_copy(field2, field1);
  383. ut_ad(dtuple_validate(search_tuple));
  384. return(search_tuple);
  385. }
  386. /*******************************************************************
  387. Builds an index definition row to insert. */
  388. static
  389. ulint
  390. dict_build_index_def_step(
  391. /*======================*/
  392. /* out: DB_SUCCESS or error code */
  393. que_thr_t* thr, /* in: query thread */
  394. ind_node_t* node) /* in: index create node */
  395. {
  396. dict_table_t* table;
  397. dict_index_t* index;
  398. dtuple_t* row;
  399. trx_t* trx;
  400. #ifdef UNIV_SYNC_DEBUG
  401. ut_ad(mutex_own(&(dict_sys->mutex)));
  402. #endif /* UNIV_SYNC_DEBUG */
  403. trx = thr_get_trx(thr);
  404. index = node->index;
  405. table = dict_table_get_low(index->table_name);
  406. if (table == NULL) {
  407. return(DB_TABLE_NOT_FOUND);
  408. }
  409. trx->table_id = table->id;
  410. node->table = table;
  411. ut_ad((UT_LIST_GET_LEN(table->indexes) > 0)
  412.       || (index->type & DICT_CLUSTERED));
  413. index->id = dict_hdr_get_new_id(DICT_HDR_INDEX_ID);
  414. /* Inherit the space id from the table; we store all indexes of a
  415. table in the same tablespace */
  416. index->space = table->space;
  417. index->page_no = FIL_NULL;
  418. row = dict_create_sys_indexes_tuple(index, node->heap);
  419. node->ind_row = row;
  420. ins_node_set_new_row(node->ind_def, row);
  421. return(DB_SUCCESS);
  422. }
  423. /*******************************************************************
  424. Builds a field definition row to insert. */
  425. static
  426. ulint
  427. dict_build_field_def_step(
  428. /*======================*/
  429. /* out: DB_SUCCESS */
  430. ind_node_t* node) /* in: index create node */
  431. {
  432. dict_index_t* index;
  433. dtuple_t* row;
  434. index = node->index;
  435. row = dict_create_sys_fields_tuple(index, node->field_no, node->heap);
  436. ins_node_set_new_row(node->field_def, row);
  437. return(DB_SUCCESS);
  438. }
  439. /*******************************************************************
  440. Creates an index tree for the index if it is not a member of a cluster. */
  441. static
  442. ulint
  443. dict_create_index_tree_step(
  444. /*========================*/
  445. /* out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
  446. ind_node_t* node) /* in: index create node */
  447. {
  448. dict_index_t* index;
  449. dict_table_t* sys_indexes;
  450. dict_table_t* table;
  451. dtuple_t* search_tuple;
  452. btr_pcur_t pcur;
  453. mtr_t mtr;
  454. #ifdef UNIV_SYNC_DEBUG
  455. ut_ad(mutex_own(&(dict_sys->mutex)));
  456. #endif /* UNIV_SYNC_DEBUG */
  457. index = node->index;
  458. table = node->table;
  459. sys_indexes = dict_sys->sys_indexes;
  460. if (index->type & DICT_CLUSTERED
  461. && table->type == DICT_TABLE_CLUSTER_MEMBER) {
  462. /* Do not create a new index tree: entries are put to the
  463. cluster tree */
  464. return(DB_SUCCESS);
  465. }
  466. /* Run a mini-transaction in which the index tree is allocated for
  467. the index and its root address is written to the index entry in
  468. sys_indexes */
  469. mtr_start(&mtr);
  470. search_tuple = dict_create_search_tuple(node->ind_row, node->heap);
  471.     
  472. btr_pcur_open(UT_LIST_GET_FIRST(sys_indexes->indexes),
  473. search_tuple, PAGE_CUR_L, BTR_MODIFY_LEAF,
  474. &pcur, &mtr);
  475. btr_pcur_move_to_next_user_rec(&pcur, &mtr);
  476. index->page_no = btr_create(index->type, index->space, index->id,
  477. &mtr);
  478. /* printf("Created a new index tree in space %lu root page %lun",
  479. index->space, index->page_no); */
  480. page_rec_write_index_page_no(btr_pcur_get_rec(&pcur),
  481. DICT_SYS_INDEXES_PAGE_NO_FIELD,
  482. index->page_no, &mtr);
  483. btr_pcur_close(&pcur);
  484. mtr_commit(&mtr);
  485. if (index->page_no == FIL_NULL) {
  486. return(DB_OUT_OF_FILE_SPACE);
  487. }
  488. return(DB_SUCCESS);
  489. }
  490. /***********************************************************************
  491. Drops the index tree associated with a row in SYS_INDEXES table. */
  492. void
  493. dict_drop_index_tree(
  494. /*=================*/
  495. rec_t* rec, /* in: record in the clustered index of SYS_INDEXES
  496. table */
  497. mtr_t* mtr) /* in: mtr having the latch on the record page */
  498. {
  499. ulint root_page_no;
  500. ulint space;
  501. byte* ptr;
  502. ulint len;
  503. #ifdef UNIV_SYNC_DEBUG
  504. ut_ad(mutex_own(&(dict_sys->mutex)));
  505. #endif /* UNIV_SYNC_DEBUG */
  506. ptr = rec_get_nth_field(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD, &len);
  507. ut_ad(len == 4);
  508. root_page_no = mtr_read_ulint(ptr, MLOG_4BYTES, mtr);
  509. if (root_page_no == FIL_NULL) {
  510. /* The tree has already been freed */
  511. return;
  512. }
  513. ptr = rec_get_nth_field(rec, DICT_SYS_INDEXES_SPACE_NO_FIELD, &len);
  514. ut_ad(len == 4);
  515. space = mtr_read_ulint(ptr, MLOG_4BYTES, mtr);
  516. if (!fil_tablespace_exists_in_mem(space)) {
  517. /* It is a single table tablespace and the .ibd file is
  518. missing: do nothing */
  519. return;
  520. }
  521. /* We free all the pages but the root page first; this operation
  522. may span several mini-transactions */
  523. btr_free_but_not_root(space, root_page_no);
  524. /* Then we free the root page in the same mini-transaction where
  525. we write FIL_NULL to the appropriate field in the SYS_INDEXES
  526. record: this mini-transaction marks the B-tree totally freed */
  527. /* printf("Dropping index tree in space %lu root page %lun", space,
  528.  root_page_no); */
  529. btr_free_root(space, root_page_no, mtr);
  530. page_rec_write_index_page_no(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD,
  531. FIL_NULL, mtr);
  532. }
  533. /*************************************************************************
  534. Creates a table create graph. */
  535. tab_node_t*
  536. tab_create_graph_create(
  537. /*====================*/
  538. /* out, own: table create node */
  539. dict_table_t* table, /* in: table to create, built as a memory data
  540. structure */
  541. mem_heap_t* heap) /* in: heap where created */
  542. {
  543. tab_node_t* node;
  544. node = mem_heap_alloc(heap, sizeof(tab_node_t));
  545. node->common.type = QUE_NODE_CREATE_TABLE;
  546. node->table = table;
  547. node->state = TABLE_BUILD_TABLE_DEF;
  548. node->heap = mem_heap_create(256);
  549. node->tab_def = ins_node_create(INS_DIRECT, dict_sys->sys_tables,
  550. heap); 
  551. node->tab_def->common.parent = node;
  552. node->col_def = ins_node_create(INS_DIRECT, dict_sys->sys_columns,
  553. heap);
  554. node->col_def->common.parent = node;
  555. node->commit_node = commit_node_create(heap);
  556. node->commit_node->common.parent = node;
  557. return(node);
  558. }
  559. /*************************************************************************
  560. Creates an index create graph. */
  561. ind_node_t*
  562. ind_create_graph_create(
  563. /*====================*/
  564. /* out, own: index create node */
  565. dict_index_t* index, /* in: index to create, built as a memory data
  566. structure */
  567. mem_heap_t* heap) /* in: heap where created */
  568. {
  569. ind_node_t* node;
  570. node = mem_heap_alloc(heap, sizeof(ind_node_t));
  571. node->common.type = QUE_NODE_CREATE_INDEX;
  572. node->index = index;
  573. node->state = INDEX_BUILD_INDEX_DEF;
  574. node->heap = mem_heap_create(256);
  575. node->ind_def = ins_node_create(INS_DIRECT,
  576. dict_sys->sys_indexes, heap); 
  577. node->ind_def->common.parent = node;
  578. node->field_def = ins_node_create(INS_DIRECT,
  579. dict_sys->sys_fields, heap);
  580. node->field_def->common.parent = node;
  581. node->commit_node = commit_node_create(heap);
  582. node->commit_node->common.parent = node;
  583. return(node);
  584. }
  585. /***************************************************************
  586. Creates a table. This is a high-level function used in SQL execution graphs. */
  587. que_thr_t*
  588. dict_create_table_step(
  589. /*===================*/
  590. /* out: query thread to run next or NULL */
  591. que_thr_t* thr) /* in: query thread */
  592. {
  593. tab_node_t* node;
  594. ulint err = DB_ERROR;
  595. trx_t* trx;
  596. ut_ad(thr);
  597. #ifdef UNIV_SYNC_DEBUG
  598. ut_ad(mutex_own(&(dict_sys->mutex)));
  599. #endif /* UNIV_SYNC_DEBUG */
  600. trx = thr_get_trx(thr);
  601. node = thr->run_node;
  602. ut_ad(que_node_get_type(node) == QUE_NODE_CREATE_TABLE);
  603. if (thr->prev_node == que_node_get_parent(node)) {
  604. node->state = TABLE_BUILD_TABLE_DEF;
  605. }
  606. if (node->state == TABLE_BUILD_TABLE_DEF) {
  607. /* DO THE CHECKS OF THE CONSISTENCY CONSTRAINTS HERE */
  608. err = dict_build_table_def_step(thr, node);
  609. if (err != DB_SUCCESS) {
  610. goto function_exit;
  611. }
  612. node->state = TABLE_BUILD_COL_DEF;
  613. node->col_no = 0;
  614. thr->run_node = node->tab_def;
  615. return(thr);
  616. }
  617. if (node->state == TABLE_BUILD_COL_DEF) {
  618. if (node->col_no < (node->table)->n_def) {
  619. err = dict_build_col_def_step(node);
  620. if (err != DB_SUCCESS) {
  621. goto function_exit;
  622. }
  623. node->col_no++;
  624. thr->run_node = node->col_def;
  625. return(thr);
  626. } else {
  627. node->state = TABLE_COMMIT_WORK;
  628. }
  629. }
  630. if (node->state == TABLE_COMMIT_WORK) {
  631. /* Table was correctly defined: do NOT commit the transaction
  632. (CREATE TABLE does NOT do an implicit commit of the current
  633. transaction) */
  634. node->state = TABLE_ADD_TO_CACHE;
  635. /* thr->run_node = node->commit_node;
  636. return(thr); */
  637. }
  638. if (node->state == TABLE_ADD_TO_CACHE) {
  639. dict_table_add_to_cache(node->table);
  640. err = DB_SUCCESS;
  641. }
  642. function_exit:
  643. trx->error_state = err;
  644. if (err == DB_SUCCESS) {
  645. /* Ok: do nothing */
  646. } else if (err == DB_LOCK_WAIT) {
  647. return(NULL);
  648. } else {
  649. /* SQL error detected */
  650. return(NULL);
  651. }
  652. thr->run_node = que_node_get_parent(node);
  653. return(thr);
  654. /***************************************************************
  655. Creates an index. This is a high-level function used in SQL execution
  656. graphs. */
  657. que_thr_t*
  658. dict_create_index_step(
  659. /*===================*/
  660. /* out: query thread to run next or NULL */
  661. que_thr_t* thr) /* in: query thread */
  662. {
  663. ind_node_t* node;
  664. ibool success;
  665. ulint err = DB_ERROR;
  666. trx_t* trx;
  667. ut_ad(thr);
  668. #ifdef UNIV_SYNC_DEBUG
  669. ut_ad(mutex_own(&(dict_sys->mutex)));
  670. #endif /* UNIV_SYNC_DEBUG */
  671. trx = thr_get_trx(thr);
  672. node = thr->run_node;
  673. ut_ad(que_node_get_type(node) == QUE_NODE_CREATE_INDEX);
  674. if (thr->prev_node == que_node_get_parent(node)) {
  675. node->state = INDEX_BUILD_INDEX_DEF;
  676. }
  677. if (node->state == INDEX_BUILD_INDEX_DEF) {
  678. /* DO THE CHECKS OF THE CONSISTENCY CONSTRAINTS HERE */
  679. err = dict_build_index_def_step(thr, node);
  680. if (err != DB_SUCCESS) {
  681. goto function_exit;
  682. }
  683. node->state = INDEX_BUILD_FIELD_DEF;
  684. node->field_no = 0;
  685. thr->run_node = node->ind_def;
  686. return(thr);
  687. }
  688. if (node->state == INDEX_BUILD_FIELD_DEF) {
  689. if (node->field_no < (node->index)->n_fields) {
  690. err = dict_build_field_def_step(node);
  691. if (err != DB_SUCCESS) {
  692. goto function_exit;
  693. }
  694. node->field_no++;
  695. thr->run_node = node->field_def;
  696. return(thr);
  697. } else {
  698. node->state = INDEX_CREATE_INDEX_TREE;
  699. }
  700. }
  701. if (node->state == INDEX_CREATE_INDEX_TREE) {
  702. err = dict_create_index_tree_step(node);
  703. if (err != DB_SUCCESS) {
  704. goto function_exit;
  705. }
  706. node->state = INDEX_COMMIT_WORK;
  707. }
  708. if (node->state == INDEX_COMMIT_WORK) {
  709. /* Index was correctly defined: do NOT commit the transaction
  710. (CREATE INDEX does NOT currently do an implicit commit of
  711. the current transaction) */
  712. node->state = INDEX_ADD_TO_CACHE;
  713. /* thr->run_node = node->commit_node;
  714. return(thr); */
  715. }
  716. if (node->state == INDEX_ADD_TO_CACHE) {
  717. success = dict_index_add_to_cache(node->table, node->index);
  718. ut_a(success);
  719. err = DB_SUCCESS;
  720. }
  721. function_exit:
  722. trx->error_state = err;
  723. if (err == DB_SUCCESS) {
  724. /* Ok: do nothing */
  725. } else if (err == DB_LOCK_WAIT) {
  726. return(NULL);
  727. } else {
  728. /* SQL error detected */
  729. return(NULL);
  730. }
  731. thr->run_node = que_node_get_parent(node);
  732. return(thr);
  733. /********************************************************************
  734. Creates the foreign key constraints system tables inside InnoDB
  735. at database creation or database start if they are not found or are
  736. not of the right form. */
  737. ulint
  738. dict_create_or_check_foreign_constraint_tables(void)
  739. /*================================================*/
  740. /* out: DB_SUCCESS or error code */
  741. {
  742. dict_table_t* table1;
  743. dict_table_t* table2;
  744. que_thr_t* thr;
  745. que_t* graph;
  746. ulint error;
  747. trx_t* trx;
  748. const char* str;
  749. mutex_enter(&(dict_sys->mutex));
  750. table1 = dict_table_get_low("SYS_FOREIGN");
  751. table2 = dict_table_get_low("SYS_FOREIGN_COLS");
  752. if (table1 && table2
  753.             && UT_LIST_GET_LEN(table1->indexes) == 3
  754.             && UT_LIST_GET_LEN(table2->indexes) == 1) {
  755.              /* Foreign constraint system tables have already been
  756.              created, and they are ok */
  757. mutex_exit(&(dict_sys->mutex));
  758.              return(DB_SUCCESS);
  759.         }
  760. mutex_exit(&(dict_sys->mutex));
  761. trx = trx_allocate_for_mysql();
  762. trx->op_info = "creating foreign key sys tables";
  763. row_mysql_lock_data_dictionary(trx);
  764. if (table1) {
  765. fprintf(stderr,
  766. "InnoDB: dropping incompletely created SYS_FOREIGN tablen");
  767. row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE);
  768. }
  769. if (table2) {
  770. fprintf(stderr,
  771. "InnoDB: dropping incompletely created SYS_FOREIGN_COLS tablen");
  772. row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE);
  773. }
  774. fprintf(stderr,
  775. "InnoDB: Creating foreign key constraint system tablesn");
  776. /* NOTE: in dict_load_foreigns we use the fact that
  777. there are 2 secondary indexes on SYS_FOREIGN, and they
  778. are defined just like below */
  779. /* NOTE: when designing InnoDB's foreign key support in 2001, we made
  780. an error and made the table names and the foreign key id of type
  781. 'CHAR' (internally, really a VARCHAR). We should have made the type
  782. VARBINARY, like in other InnoDB system tables, to get a clean
  783. design. */
  784. str =
  785. "PROCEDURE CREATE_FOREIGN_SYS_TABLES_PROC () ISn"
  786. "BEGINn"
  787. "CREATE TABLEn"
  788. "SYS_FOREIGN(ID CHAR, FOR_NAME CHAR, REF_NAME CHAR, N_COLS INT);n"
  789. "CREATE UNIQUE CLUSTERED INDEX ID_IND ON SYS_FOREIGN (ID);n"
  790. "CREATE INDEX FOR_IND ON SYS_FOREIGN (FOR_NAME);n"
  791. "CREATE INDEX REF_IND ON SYS_FOREIGN (REF_NAME);n"
  792. "CREATE TABLEn"
  793.   "SYS_FOREIGN_COLS(ID CHAR, POS INT, FOR_COL_NAME CHAR, REF_COL_NAME CHAR);n"
  794. "CREATE UNIQUE CLUSTERED INDEX ID_IND ON SYS_FOREIGN_COLS (ID, POS);n"
  795. "COMMIT WORK;n"
  796. "END;n";
  797. graph = pars_sql(str);
  798. ut_a(graph);
  799. graph->trx = trx;
  800. trx->graph = NULL;
  801. graph->fork_type = QUE_FORK_MYSQL_INTERFACE;
  802. ut_a(thr = que_fork_start_command(graph));
  803. que_run_threads(thr);
  804. error = trx->error_state;
  805. if (error != DB_SUCCESS) {
  806. fprintf(stderr, "InnoDB: error %lu in creationn",
  807. (ulong) error);
  808. ut_a(error == DB_OUT_OF_FILE_SPACE);
  809. fprintf(stderr, "InnoDB: creation failedn");
  810. fprintf(stderr, "InnoDB: tablespace is fulln");
  811. fprintf(stderr,
  812. "InnoDB: dropping incompletely created SYS_FOREIGN tablesn");
  813. row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE);
  814. row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE);
  815. error = DB_MUST_GET_MORE_FILE_SPACE;
  816. }
  817. que_graph_free(graph);
  818. trx->op_info = "";
  819. row_mysql_unlock_data_dictionary(trx);
  820.    trx_free_for_mysql(trx);
  821.    if (error == DB_SUCCESS) {
  822. fprintf(stderr,
  823. "InnoDB: Foreign key constraint system tables createdn");
  824. }
  825. return(error);
  826. }
  827. /************************************************************************
  828. Adds foreign key definitions to data dictionary tables in the database. We
  829. look at table->foreign_list, and also generate names to constraints that were
  830. not named by the user. A generated constraint has a name of the format
  831. databasename/tablename_ibfk_<number>, where the numbers start from 1, and are
  832. given locally for this table, that is, the number is not global, as in the
  833. old format constraints < 4.0.18 it used to be. */
  834. ulint
  835. dict_create_add_foreigns_to_dictionary(
  836. /*===================================*/
  837. /* out: error code or DB_SUCCESS */
  838. ulint start_id,/* in: if we are actually doing ALTER TABLE
  839. ADD CONSTRAINT, we want to generate constraint
  840. numbers which are bigger than in the table so
  841. far; we number the constraints from
  842. start_id + 1 up; start_id should be set to 0 if
  843. we are creating a new table, or if the table
  844. so far has no constraints for which the name
  845. was generated here */
  846. dict_table_t* table, /* in: table */
  847. trx_t* trx) /* in: transaction */
  848. {
  849. dict_foreign_t* foreign;
  850. que_thr_t* thr;
  851. que_t* graph;
  852. ulint number = start_id + 1;
  853. ulint len;
  854. ulint error;
  855. FILE* ef = dict_foreign_err_file;
  856. ulint i;
  857. char* sql;
  858. char* sqlend;
  859. /* This procedure builds an InnoDB stored procedure which will insert
  860. the necessary rows into SYS_FOREIGN and SYS_FOREIGN_COLS. */
  861. static const char str1[] = "PROCEDURE ADD_FOREIGN_DEFS_PROC () ISn"
  862. "BEGINn"
  863. "INSERT INTO SYS_FOREIGN VALUES(";
  864. static const char str2[] = ");n";
  865. static const char str3[] =
  866. "INSERT INTO SYS_FOREIGN_COLS VALUES(";
  867. static const char str4[] =
  868. "COMMIT WORK;n"
  869. "END;n";
  870. #ifdef UNIV_SYNC_DEBUG
  871. ut_ad(mutex_own(&(dict_sys->mutex)));
  872. #endif /* UNIV_SYNC_DEBUG */
  873. if (NULL == dict_table_get_low("SYS_FOREIGN")) {
  874. fprintf(stderr,
  875.      "InnoDB: table SYS_FOREIGN not found from internal data dictionaryn");
  876. return(DB_ERROR);
  877. }
  878. foreign = UT_LIST_GET_FIRST(table->foreign_list);
  879. loop:
  880. if (foreign == NULL) {
  881. return(DB_SUCCESS);
  882. }
  883. if (foreign->id == NULL) {
  884. /* Generate a new constraint id */
  885. ulint namelen = strlen(table->name);
  886. char* id = mem_heap_alloc(foreign->heap, namelen + 20);
  887. /* no overflow if number < 1e13 */
  888. sprintf(id, "%s_ibfk_%lu", table->name, (ulong) number++);
  889. foreign->id = id;
  890. }
  891. len = (sizeof str1) + (sizeof str2) + (sizeof str4) - 3
  892. + 9/* ' and , chars */ + 10/* 32-bit integer */
  893. + ut_strlenq(foreign->id, ''') * (foreign->n_fields + 1)
  894. + ut_strlenq(table->name, ''')
  895. + ut_strlenq(foreign->referenced_table_name, ''');
  896. for (i = 0; i < foreign->n_fields; i++) {
  897. len += 9/* ' and , chars */ + 10/* 32-bit integer */
  898. + (sizeof str3) + (sizeof str2) - 2
  899. + ut_strlenq(foreign->foreign_col_names[i], ''')
  900. + ut_strlenq(foreign->referenced_col_names[i], ''');
  901. }
  902. sql = sqlend = mem_alloc(len + 1);
  903. /* INSERT INTO SYS_FOREIGN VALUES(...); */
  904. memcpy(sqlend, str1, (sizeof str1) - 1);
  905. sqlend += (sizeof str1) - 1;
  906. *sqlend++ = ''';
  907. sqlend = ut_strcpyq(sqlend, ''', foreign->id);
  908. *sqlend++ = ''', *sqlend++ = ',', *sqlend++ = ''';
  909. sqlend = ut_strcpyq(sqlend, ''', table->name);
  910. *sqlend++ = ''', *sqlend++ = ',', *sqlend++ = ''';
  911. sqlend = ut_strcpyq(sqlend, ''', foreign->referenced_table_name);
  912. *sqlend++ = ''', *sqlend++ = ',';
  913. sqlend += sprintf(sqlend, "%010lu",
  914. foreign->n_fields + (foreign->type << 24));
  915. memcpy(sqlend, str2, (sizeof str2) - 1);
  916. sqlend += (sizeof str2) - 1;
  917. for (i = 0; i < foreign->n_fields; i++) {
  918. /* INSERT INTO SYS_FOREIGN_COLS VALUES(...); */
  919. memcpy(sqlend, str3, (sizeof str3) - 1);
  920. sqlend += (sizeof str3) - 1;
  921. *sqlend++ = ''';
  922. sqlend = ut_strcpyq(sqlend, ''', foreign->id);
  923. *sqlend++ = '''; *sqlend++ = ',';
  924. sqlend += sprintf(sqlend, "%010lu", (ulong) i);
  925. *sqlend++ = ','; *sqlend++ = ''';
  926. sqlend = ut_strcpyq(sqlend, ''',
  927. foreign->foreign_col_names[i]);
  928. *sqlend++ = '''; *sqlend++ = ','; *sqlend++ = ''';
  929. sqlend = ut_strcpyq(sqlend, ''',
  930. foreign->referenced_col_names[i]);
  931. *sqlend++ = ''';
  932. memcpy(sqlend, str2, (sizeof str2) - 1);
  933. sqlend += (sizeof str2) - 1;
  934. }
  935. memcpy(sqlend, str4, sizeof str4);
  936. sqlend += sizeof str4;
  937. ut_a(sqlend == sql + len + 1);
  938. graph = pars_sql(sql);
  939. ut_a(graph);
  940. mem_free(sql);
  941. graph->trx = trx;
  942. trx->graph = NULL;
  943. graph->fork_type = QUE_FORK_MYSQL_INTERFACE;
  944. ut_a(thr = que_fork_start_command(graph));
  945. que_run_threads(thr);
  946. error = trx->error_state;
  947. que_graph_free(graph);
  948. if (error == DB_DUPLICATE_KEY) {
  949. mutex_enter(&dict_foreign_err_mutex);
  950. rewind(ef);
  951. ut_print_timestamp(ef);
  952. fputs(" Error in foreign key constraint creation for table ",
  953. ef);
  954. ut_print_name(ef, trx, table->name);
  955. fputs(".nA foreign key constraint of name ", ef);
  956. ut_print_name(ef, trx, foreign->id);
  957. fputs("nalready exists."
  958. " (Note that internally InnoDB adds 'databasename/'n"
  959. "in front of the user-defined constraint name).n",
  960. ef);
  961. fputs("Note that InnoDB's FOREIGN KEY system tables storen"
  962.       "constraint names as case-insensitive, with then"
  963.       "MySQL standard latin1_swedish_ci collation. If youn"
  964.       "create tables or databases whose names differ only inn"
  965.       "the character case, then collisions in constraintn"
  966.       "names can occur. Workaround: name your constraintsn"
  967.       "explicitly with unique names.n",
  968. ef);
  969. mutex_exit(&dict_foreign_err_mutex);
  970. return(error);
  971. }
  972. if (error != DB_SUCCESS) {
  973.         fprintf(stderr,
  974. "InnoDB: Foreign key constraint creation failed:n"
  975. "InnoDB: internal error number %lun", (ulong) error);
  976. mutex_enter(&dict_foreign_err_mutex);
  977. ut_print_timestamp(ef);
  978. fputs(" Internal error in foreign key constraint creation"
  979. " for table ", ef);
  980. ut_print_name(ef, trx, table->name);
  981. fputs(".n"
  982. "See the MySQL .err log in the datadir for more information.n", ef);
  983. mutex_exit(&dict_foreign_err_mutex);
  984. return(error);
  985. }
  986. foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
  987. goto loop;
  988. }