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

MySQL数据库

开发平台:

Visual C++

  1. /**********************************************************************
  2. Data dictionary system
  3. (c) 1996 Innobase Oy
  4. Created 1/8/1996 Heikki Tuuri
  5. ***********************************************************************/
  6. #include "dict0dict.h"
  7. #ifdef UNIV_NONINL
  8. #include "dict0dict.ic"
  9. #endif
  10. #include "buf0buf.h"
  11. #include "data0type.h"
  12. #include "mach0data.h"
  13. #include "dict0boot.h"
  14. #include "dict0mem.h"
  15. #include "dict0crea.h"
  16. #include "trx0undo.h"
  17. #include "btr0btr.h"
  18. #include "btr0cur.h"
  19. #include "btr0sea.h"
  20. #include "pars0pars.h"
  21. #include "pars0sym.h"
  22. #include "que0que.h"
  23. #include "rem0cmp.h"
  24. dict_sys_t* dict_sys = NULL; /* the dictionary system */
  25. rw_lock_t dict_operation_lock; /* table create, drop, etc. reserve
  26. this in X-mode; implicit or backround
  27. operations purge, rollback, foreign
  28. key checks reserve this in S-mode; we
  29. cannot trust that MySQL protects
  30. implicit or background operations
  31. a table drop since MySQL does not
  32. know of them; therefore we need this;
  33. NOTE: a transaction which reserves
  34. this must keep book on the mode in
  35. trx->dict_operation_lock_mode */
  36. #define DICT_HEAP_SIZE 100 /* initial memory heap size when
  37. creating a table or index object */
  38. #define DICT_POOL_PER_TABLE_HASH 512 /* buffer pool max size per table
  39. hash table fixed size in bytes */
  40. #define DICT_POOL_PER_COL_HASH 128 /* buffer pool max size per column
  41. hash table fixed size in bytes */
  42. #define DICT_POOL_PER_VARYING 4 /* buffer pool max size per data
  43. dictionary varying size in bytes */
  44. /* Identifies generated InnoDB foreign key names */
  45. static char dict_ibfk[] = "_ibfk_";
  46. /**********************************************************************
  47. Compares NUL-terminated UTF-8 strings case insensitively.
  48. NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
  49. this function, you MUST change also the prototype here! */
  50. extern
  51. int
  52. innobase_strcasecmp(
  53. /*================*/
  54. /* out: 0 if a=b, <0 if a<b, >1 if a>b */
  55. const char* a, /* in: first string to compare */
  56. const char* b); /* in: second string to compare */
  57. /**********************************************************************
  58. Makes all characters in a NUL-terminated UTF-8 string lower case.
  59. NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
  60. this function, you MUST change also the prototype here! */
  61. extern
  62. void
  63. innobase_casedn_str(
  64. /*================*/
  65. char* a); /* in/out: string to put in lower case */
  66. /**************************************************************************
  67. Adds a column to the data dictionary hash table. */
  68. static
  69. void
  70. dict_col_add_to_cache(
  71. /*==================*/
  72. dict_table_t* table, /* in: table */
  73. dict_col_t* col); /* in: column */
  74. /**************************************************************************
  75. Repositions a column in the data dictionary hash table when the table name
  76. changes. */
  77. static
  78. void
  79. dict_col_reposition_in_cache(
  80. /*=========================*/
  81. dict_table_t* table, /* in: table */
  82. dict_col_t* col, /* in: column */
  83. const char* new_name); /* in: new table name */
  84. /**************************************************************************
  85. Removes a column from the data dictionary hash table. */
  86. static
  87. void
  88. dict_col_remove_from_cache(
  89. /*=======================*/
  90. dict_table_t* table, /* in: table */
  91. dict_col_t* col); /* in: column */
  92. /**************************************************************************
  93. Removes an index from the dictionary cache. */
  94. static
  95. void
  96. dict_index_remove_from_cache(
  97. /*=========================*/
  98. dict_table_t* table, /* in: table */
  99. dict_index_t* index); /* in, own: index */
  100. /***********************************************************************
  101. Copies fields contained in index2 to index1. */
  102. static
  103. void
  104. dict_index_copy(
  105. /*============*/
  106. dict_index_t* index1, /* in: index to copy to */
  107. dict_index_t* index2, /* in: index to copy from */
  108. ulint start, /* in: first position to copy */
  109. ulint end); /* in: last position to copy */
  110. /***********************************************************************
  111. Tries to find column names for the index in the column hash table and
  112. sets the col field of the index. */
  113. static
  114. ibool
  115. dict_index_find_cols(
  116. /*=================*/
  117. /* out: TRUE if success */
  118. dict_table_t* table, /* in: table */
  119. dict_index_t* index); /* in: index */
  120. /***********************************************************************
  121. Builds the internal dictionary cache representation for a clustered
  122. index, containing also system fields not defined by the user. */
  123. static
  124. dict_index_t*
  125. dict_index_build_internal_clust(
  126. /*============================*/
  127. /* out, own: the internal representation
  128. of the clustered index */
  129. dict_table_t* table, /* in: table */
  130. dict_index_t* index); /* in: user representation of a clustered
  131. index */
  132. /***********************************************************************
  133. Builds the internal dictionary cache representation for a non-clustered
  134. index, containing also system fields not defined by the user. */
  135. static
  136. dict_index_t*
  137. dict_index_build_internal_non_clust(
  138. /*================================*/
  139. /* out, own: the internal representation
  140. of the non-clustered index */
  141. dict_table_t* table, /* in: table */
  142. dict_index_t* index); /* in: user representation of a non-clustered
  143. index */
  144. /**************************************************************************
  145. Removes a foreign constraint struct from the dictionary cache. */
  146. static
  147. void
  148. dict_foreign_remove_from_cache(
  149. /*===========================*/
  150. dict_foreign_t* foreign); /* in, own: foreign constraint */
  151. /**************************************************************************
  152. Prints a column data. */
  153. static
  154. void
  155. dict_col_print_low(
  156. /*===============*/
  157. dict_col_t* col); /* in: column */
  158. /**************************************************************************
  159. Prints an index data. */
  160. static
  161. void
  162. dict_index_print_low(
  163. /*=================*/
  164. dict_index_t* index); /* in: index */
  165. /**************************************************************************
  166. Prints a field data. */
  167. static
  168. void
  169. dict_field_print_low(
  170. /*=================*/
  171. dict_field_t* field); /* in: field */
  172. /*************************************************************************
  173. Frees a foreign key struct. */
  174. static
  175. void
  176. dict_foreign_free(
  177. /*==============*/
  178. dict_foreign_t* foreign); /* in, own: foreign key struct */
  179. /* Stream for storing detailed information about the latest foreign key
  180. and unique key errors */
  181. FILE* dict_foreign_err_file = NULL;
  182. mutex_t dict_foreign_err_mutex;  /* mutex protecting the foreign
  183. and unique error buffers */
  184. /**********************************************************************
  185. Makes all characters in a NUL-terminated UTF-8 string lower case. */
  186. void
  187. dict_casedn_str(
  188. /*============*/
  189. char* a) /* in/out: string to put in lower case */
  190. {
  191. innobase_casedn_str(a);
  192. }
  193. /************************************************************************
  194. Checks if the database name in two table names is the same. */
  195. ibool
  196. dict_tables_have_same_db(
  197. /*=====================*/
  198. /* out: TRUE if same db name */
  199. const char* name1, /* in: table name in the form
  200. dbname '/' tablename */
  201. const char* name2) /* in: table name in the form
  202. dbname '/' tablename */
  203. {
  204. for (; *name1 == *name2; name1++, name2++) {
  205. if (*name1 == '/') {
  206. return(TRUE);
  207. }
  208. ut_a(*name1); /* the names must contain '/' */
  209. }
  210. return(FALSE);
  211. }
  212. /************************************************************************
  213. Return the end of table name where we have removed dbname and '/'. */
  214. static
  215. const char*
  216. dict_remove_db_name(
  217. /*================*/
  218. /* out: table name */
  219. const char* name) /* in: table name in the form
  220. dbname '/' tablename */
  221. {
  222. const char* s;
  223. s = strchr(name, '/');
  224. ut_a(s);
  225. if (s) s++;
  226. return(s);
  227. }
  228. /************************************************************************
  229. Get the database name length in a table name. */
  230. ulint
  231. dict_get_db_name_len(
  232. /*=================*/
  233. /* out: database name length */
  234. const char* name) /* in: table name in the form
  235. dbname '/' tablename */
  236. {
  237. const char* s;
  238. s = strchr(name, '/');
  239. ut_a(s);
  240. return(s - name);
  241. }
  242. /************************************************************************
  243. Reserves the dictionary system mutex for MySQL. */
  244. void
  245. dict_mutex_enter_for_mysql(void)
  246. /*============================*/
  247. {
  248. mutex_enter(&(dict_sys->mutex));
  249. }
  250. /************************************************************************
  251. Releases the dictionary system mutex for MySQL. */
  252. void
  253. dict_mutex_exit_for_mysql(void)
  254. /*===========================*/
  255. {
  256. mutex_exit(&(dict_sys->mutex));
  257. }
  258. /************************************************************************
  259. Decrements the count of open MySQL handles to a table. */
  260. void
  261. dict_table_decrement_handle_count(
  262. /*==============================*/
  263. dict_table_t* table) /* in: table */
  264. {
  265. mutex_enter(&(dict_sys->mutex));
  266. ut_a(table->n_mysql_handles_opened > 0);
  267. table->n_mysql_handles_opened--;
  268. mutex_exit(&(dict_sys->mutex));
  269. }
  270. /************************************************************************
  271. Gets the nth column of a table. */
  272. dict_col_t*
  273. dict_table_get_nth_col_noninline(
  274. /*=============================*/
  275. /* out: pointer to column object */
  276. dict_table_t* table, /* in: table */
  277. ulint pos) /* in: position of column */
  278. {
  279. return(dict_table_get_nth_col(table, pos));
  280. }
  281. /************************************************************************
  282. Gets the first index on the table (the clustered index). */
  283. dict_index_t*
  284. dict_table_get_first_index_noninline(
  285. /*=================================*/
  286. /* out: index, NULL if none exists */
  287. dict_table_t* table) /* in: table */
  288. {
  289. return(dict_table_get_first_index(table));
  290. }
  291. /************************************************************************
  292. Gets the next index on the table. */
  293. dict_index_t*
  294. dict_table_get_next_index_noninline(
  295. /*================================*/
  296. /* out: index, NULL if none left */
  297. dict_index_t* index) /* in: index */
  298. {
  299. return(dict_table_get_next_index(index));
  300. }
  301. /**************************************************************************
  302. Returns an index object. */
  303. dict_index_t*
  304. dict_table_get_index_noninline(
  305. /*===========================*/
  306. /* out: index, NULL if does not exist */
  307. dict_table_t* table, /* in: table */
  308. const char* name) /* in: index name */
  309. {
  310. return(dict_table_get_index(table, name));
  311. }
  312. /************************************************************************
  313. Initializes the autoinc counter. It is not an error to initialize an already
  314. initialized counter. */
  315. void
  316. dict_table_autoinc_initialize(
  317. /*==========================*/
  318. dict_table_t* table, /* in: table */
  319. ib_longlong value) /* in: next value to assign to a row */
  320. {
  321. mutex_enter(&(table->autoinc_mutex));
  322. table->autoinc_inited = TRUE;
  323. table->autoinc = value;
  324. mutex_exit(&(table->autoinc_mutex));
  325. }
  326. /************************************************************************
  327. Gets the next autoinc value (== autoinc counter value), 0 if not yet
  328. initialized. If initialized, increments the counter by 1. */
  329. ib_longlong
  330. dict_table_autoinc_get(
  331. /*===================*/
  332. /* out: value for a new row, or 0 */
  333. dict_table_t* table) /* in: table */
  334. {
  335. ib_longlong value;
  336. mutex_enter(&(table->autoinc_mutex));
  337. if (!table->autoinc_inited) {
  338. value = 0;
  339. } else {
  340. value = table->autoinc;
  341. table->autoinc = table->autoinc + 1;
  342. }
  343. mutex_exit(&(table->autoinc_mutex));
  344. return(value);
  345. }
  346. /************************************************************************
  347. Decrements the autoinc counter value by 1. */
  348. void
  349. dict_table_autoinc_decrement(
  350. /*=========================*/
  351. dict_table_t* table) /* in: table */
  352. {
  353. mutex_enter(&(table->autoinc_mutex));
  354. table->autoinc = table->autoinc - 1;
  355. mutex_exit(&(table->autoinc_mutex));
  356. }
  357. /************************************************************************
  358. Reads the next autoinc value (== autoinc counter value), 0 if not yet
  359. initialized. */
  360. ib_longlong
  361. dict_table_autoinc_read(
  362. /*====================*/
  363. /* out: value for a new row, or 0 */
  364. dict_table_t* table) /* in: table */
  365. {
  366. ib_longlong value;
  367. mutex_enter(&(table->autoinc_mutex));
  368. if (!table->autoinc_inited) {
  369. value = 0;
  370. } else {
  371. value = table->autoinc;
  372. }
  373. mutex_exit(&(table->autoinc_mutex));
  374. return(value);
  375. }
  376. /************************************************************************
  377. Peeks the autoinc counter value, 0 if not yet initialized. Does not
  378. increment the counter. The read not protected by any mutex! */
  379. ib_longlong
  380. dict_table_autoinc_peek(
  381. /*====================*/
  382. /* out: value of the counter */
  383. dict_table_t* table) /* in: table */
  384. {
  385. ib_longlong value;
  386. if (!table->autoinc_inited) {
  387. value = 0;
  388. } else {
  389. value = table->autoinc;
  390. }
  391. return(value);
  392. }
  393. /************************************************************************
  394. Updates the autoinc counter if the value supplied is equal or bigger than the
  395. current value. If not inited, does nothing. */
  396. void
  397. dict_table_autoinc_update(
  398. /*======================*/
  399. dict_table_t* table, /* in: table */
  400. ib_longlong value) /* in: value which was assigned to a row */
  401. {
  402. mutex_enter(&(table->autoinc_mutex));
  403. if (table->autoinc_inited) {
  404. if (value >= table->autoinc) {
  405. table->autoinc = value + 1;
  406. }
  407. }
  408. mutex_exit(&(table->autoinc_mutex));
  409. }
  410. /************************************************************************
  411. Looks for column n in an index. */
  412. ulint
  413. dict_index_get_nth_col_pos(
  414. /*=======================*/
  415. /* out: position in internal representation
  416. of the index; if not contained, returns
  417. ULINT_UNDEFINED */
  418. dict_index_t* index, /* in: index */
  419. ulint n) /* in: column number */
  420. {
  421. dict_field_t* field;
  422. dict_col_t* col;
  423. ulint pos;
  424. ulint n_fields;
  425. ut_ad(index);
  426. ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
  427. col = dict_table_get_nth_col(index->table, n);
  428. if (index->type & DICT_CLUSTERED) {
  429. return(col->clust_pos);
  430. }
  431. n_fields = dict_index_get_n_fields(index);
  432. for (pos = 0; pos < n_fields; pos++) {
  433. field = dict_index_get_nth_field(index, pos);
  434. if (col == field->col && field->prefix_len == 0) {
  435. return(pos);
  436. }
  437. }
  438. return(ULINT_UNDEFINED);
  439. }
  440. /************************************************************************
  441. Returns TRUE if the index contains a column or a prefix of that column. */
  442. ibool
  443. dict_index_contains_col_or_prefix(
  444. /*==============================*/
  445. /* out: TRUE if contains the column or its
  446. prefix */
  447. dict_index_t* index, /* in: index */
  448. ulint n) /* in: column number */
  449. {
  450. dict_field_t* field;
  451. dict_col_t* col;
  452. ulint pos;
  453. ulint n_fields;
  454. ut_ad(index);
  455. ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
  456. if (index->type & DICT_CLUSTERED) {
  457. return(TRUE);
  458. }
  459. col = dict_table_get_nth_col(index->table, n);
  460. n_fields = dict_index_get_n_fields(index);
  461. for (pos = 0; pos < n_fields; pos++) {
  462. field = dict_index_get_nth_field(index, pos);
  463. if (col == field->col) {
  464. return(TRUE);
  465. }
  466. }
  467. return(FALSE);
  468. }
  469. /************************************************************************
  470. Looks for a matching field in an index. The column has to be the same. The
  471. column in index must be complete, or must contain a prefix longer than the
  472. column in index2. That is, we must be able to construct the prefix in index2
  473. from the prefix in index. */
  474. ulint
  475. dict_index_get_nth_field_pos(
  476. /*=========================*/
  477. /* out: position in internal representation
  478. of the index; if not contained, returns
  479. ULINT_UNDEFINED */
  480. dict_index_t* index, /* in: index from which to search */
  481. dict_index_t* index2, /* in: index */
  482. ulint n) /* in: field number in index2 */
  483. {
  484. dict_field_t* field;
  485. dict_field_t* field2;
  486. ulint n_fields;
  487. ulint pos;
  488. ut_ad(index);
  489. ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
  490. field2 = dict_index_get_nth_field(index2, n);
  491. n_fields = dict_index_get_n_fields(index);
  492. for (pos = 0; pos < n_fields; pos++) {
  493. field = dict_index_get_nth_field(index, pos);
  494. if (field->col == field2->col
  495.     && (field->prefix_len == 0
  496. || (field->prefix_len >= field2->prefix_len
  497.     && field2->prefix_len != 0))) {
  498. return(pos);
  499. }
  500. }
  501. return(ULINT_UNDEFINED);
  502. }
  503. /**************************************************************************
  504. Returns a table object, based on table id, and memoryfixes it. */
  505. dict_table_t*
  506. dict_table_get_on_id(
  507. /*=================*/
  508. /* out: table, NULL if does not exist */
  509. dulint table_id, /* in: table id */
  510. trx_t* trx) /* in: transaction handle */
  511. {
  512. dict_table_t* table;
  513. if (ut_dulint_cmp(table_id, DICT_FIELDS_ID) <= 0
  514.    || trx->dict_operation_lock_mode == RW_X_LATCH) {
  515. /* It is a system table which will always exist in the table
  516. cache: we avoid acquiring the dictionary mutex, because
  517. if we are doing a rollback to handle an error in TABLE
  518. CREATE, for example, we already have the mutex! */
  519. #ifdef UNIV_SYNC_DEBUG
  520. ut_ad(mutex_own(&(dict_sys->mutex)));
  521. #endif /* UNIV_SYNC_DEBUG */
  522. return(dict_table_get_on_id_low(table_id, trx));
  523. }
  524. mutex_enter(&(dict_sys->mutex));
  525. table = dict_table_get_on_id_low(table_id, trx);
  526. mutex_exit(&(dict_sys->mutex));
  527. return(table);
  528. }
  529. /************************************************************************
  530. Looks for column n position in the clustered index. */
  531. ulint
  532. dict_table_get_nth_col_pos(
  533. /*=======================*/
  534. /* out: position in internal representation
  535. of the clustered index */
  536. dict_table_t* table, /* in: table */
  537. ulint n) /* in: column number */
  538. {
  539. return(dict_index_get_nth_col_pos(dict_table_get_first_index(table),
  540. n));
  541. }
  542. /************************************************************************
  543. Checks if a column is in the ordering columns of the clustered index of a
  544. table. Column prefixes are treated like whole columns. */
  545. ibool
  546. dict_table_col_in_clustered_key(
  547. /*============================*/
  548. /* out: TRUE if the column, or its prefix, is
  549. in the clustered key */
  550. dict_table_t* table, /* in: table */
  551. ulint n) /* in: column number */
  552. {
  553. dict_index_t* index;
  554. dict_field_t* field;
  555. dict_col_t* col;
  556. ulint pos;
  557. ulint n_fields;
  558. ut_ad(table);
  559. col = dict_table_get_nth_col(table, n);
  560. index = dict_table_get_first_index(table);
  561. n_fields = dict_index_get_n_unique(index);
  562. for (pos = 0; pos < n_fields; pos++) {
  563. field = dict_index_get_nth_field(index, pos);
  564. if (col == field->col) {
  565. return(TRUE);
  566. }
  567. }
  568. return(FALSE);
  569. }
  570. /**************************************************************************
  571. Inits the data dictionary module. */
  572. void
  573. dict_init(void)
  574. /*===========*/
  575. {
  576. dict_sys = mem_alloc(sizeof(dict_sys_t));
  577. mutex_create(&(dict_sys->mutex));
  578. mutex_set_level(&(dict_sys->mutex), SYNC_DICT);
  579. dict_sys->table_hash = hash_create(buf_pool_get_max_size() /
  580. (DICT_POOL_PER_TABLE_HASH *
  581. UNIV_WORD_SIZE));
  582. dict_sys->table_id_hash = hash_create(buf_pool_get_max_size() /
  583. (DICT_POOL_PER_TABLE_HASH *
  584. UNIV_WORD_SIZE));
  585. dict_sys->col_hash = hash_create(buf_pool_get_max_size() /
  586. (DICT_POOL_PER_COL_HASH *
  587. UNIV_WORD_SIZE));
  588. dict_sys->size = 0;
  589. UT_LIST_INIT(dict_sys->table_LRU);
  590. rw_lock_create(&dict_operation_lock);
  591. rw_lock_set_level(&dict_operation_lock, SYNC_DICT_OPERATION);
  592. dict_foreign_err_file = os_file_create_tmpfile();
  593. ut_a(dict_foreign_err_file);
  594. mutex_create(&dict_foreign_err_mutex);
  595. mutex_set_level(&dict_foreign_err_mutex, SYNC_ANY_LATCH);
  596. }
  597. /**************************************************************************
  598. Returns a table object and memoryfixes it. NOTE! This is a high-level
  599. function to be used mainly from outside the 'dict' directory. Inside this
  600. directory dict_table_get_low is usually the appropriate function. */
  601. dict_table_t*
  602. dict_table_get(
  603. /*===========*/
  604. /* out: table, NULL if
  605. does not exist */
  606. const char* table_name, /* in: table name */
  607. trx_t* trx) /* in: transaction handle or NULL */
  608. {
  609. dict_table_t* table;
  610. UT_NOT_USED(trx);
  611. mutex_enter(&(dict_sys->mutex));
  612. table = dict_table_get_low(table_name);
  613. mutex_exit(&(dict_sys->mutex));
  614. if (table != NULL) {
  615.         if (!table->stat_initialized) {
  616. dict_update_statistics(table);
  617. }
  618. }
  619. return(table);
  620. }
  621. /**************************************************************************
  622. Returns a table object and increments MySQL open handle count on the table. */
  623. dict_table_t*
  624. dict_table_get_and_increment_handle_count(
  625. /*======================================*/
  626. /* out: table, NULL if
  627. does not exist */
  628. const char* table_name, /* in: table name */
  629. trx_t* trx) /* in: transaction handle or NULL */
  630. {
  631. dict_table_t* table;
  632. UT_NOT_USED(trx);
  633. mutex_enter(&(dict_sys->mutex));
  634. table = dict_table_get_low(table_name);
  635. if (table != NULL) {
  636.         table->n_mysql_handles_opened++;
  637. }
  638. mutex_exit(&(dict_sys->mutex));
  639. if (table != NULL) {
  640.         if (!table->stat_initialized && !table->ibd_file_missing) {
  641. dict_update_statistics(table);
  642. }
  643. }
  644. return(table);
  645. }
  646. /**************************************************************************
  647. Adds a table object to the dictionary cache. */
  648. void
  649. dict_table_add_to_cache(
  650. /*====================*/
  651. dict_table_t* table) /* in: table */
  652. {
  653. ulint fold;
  654. ulint id_fold;
  655. ulint i;
  656. ut_ad(table);
  657. #ifdef UNIV_SYNC_DEBUG
  658. ut_ad(mutex_own(&(dict_sys->mutex)));
  659. #endif /* UNIV_SYNC_DEBUG */
  660. ut_ad(table->n_def == table->n_cols - DATA_N_SYS_COLS);
  661. ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
  662. ut_ad(table->cached == FALSE);
  663. fold = ut_fold_string(table->name);
  664. id_fold = ut_fold_dulint(table->id);
  665. table->cached = TRUE;
  666. /* NOTE: the system columns MUST be added in the following order
  667. (so that they can be indexed by the numerical value of DATA_ROW_ID,
  668. etc.) and as the last columns of the table memory object.
  669. The clustered index will not always physically contain all
  670. system columns. */
  671. dict_mem_table_add_col(table, "DB_ROW_ID", DATA_SYS,
  672.        DATA_ROW_ID, 0, 0);
  673. #if DATA_ROW_ID != 0
  674. #error "DATA_ROW_ID != 0"
  675. #endif
  676. dict_mem_table_add_col(table, "DB_TRX_ID", DATA_SYS,
  677.        DATA_TRX_ID, 0, 0);
  678. #if DATA_TRX_ID != 1
  679. #error "DATA_TRX_ID != 1"
  680. #endif
  681. dict_mem_table_add_col(table, "DB_ROLL_PTR", DATA_SYS,
  682.        DATA_ROLL_PTR, 0, 0);
  683. #if DATA_ROLL_PTR != 2
  684. #error "DATA_ROLL_PTR != 2"
  685. #endif
  686. dict_mem_table_add_col(table, "DB_MIX_ID", DATA_SYS,
  687.        DATA_MIX_ID, 0, 0);
  688. #if DATA_MIX_ID != 3
  689. #error "DATA_MIX_ID != 3"
  690. #endif
  691. /* This check reminds that if a new system column is added to
  692. the program, it should be dealt with here */ 
  693. #if DATA_N_SYS_COLS != 4
  694. #error "DATA_N_SYS_COLS != 4"
  695. #endif
  696. /* Look for a table with the same name: error if such exists */
  697. {
  698. dict_table_t* table2;
  699. HASH_SEARCH(name_hash, dict_sys->table_hash, fold, table2,
  700. (ut_strcmp(table2->name, table->name) == 0));
  701. ut_a(table2 == NULL);
  702. }
  703. /* Look for a table with the same id: error if such exists */
  704. {
  705. dict_table_t* table2;
  706. HASH_SEARCH(id_hash, dict_sys->table_id_hash, id_fold, table2,
  707. (ut_dulint_cmp(table2->id, table->id) == 0));
  708. ut_a(table2 == NULL);
  709. }
  710. if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
  711. table->mix_id_len = mach_dulint_get_compressed_size(
  712. table->mix_id);
  713. mach_dulint_write_compressed(table->mix_id_buf, table->mix_id);
  714. }
  715. /* Add the columns to the column hash table */
  716. for (i = 0; i < table->n_cols; i++) {
  717. dict_col_add_to_cache(table, dict_table_get_nth_col(table, i));
  718. }
  719. /* Add table to hash table of tables */
  720. HASH_INSERT(dict_table_t, name_hash, dict_sys->table_hash, fold,
  721.    table);
  722. /* Add table to hash table of tables based on table id */
  723. HASH_INSERT(dict_table_t, id_hash, dict_sys->table_id_hash, id_fold,
  724.    table);
  725. /* Add table to LRU list of tables */
  726. UT_LIST_ADD_FIRST(table_LRU, dict_sys->table_LRU, table);
  727. /* If the dictionary cache grows too big, trim the table LRU list */
  728. dict_sys->size += mem_heap_get_size(table->heap);
  729. /* dict_table_LRU_trim(); */
  730. }
  731. /**************************************************************************
  732. Looks for an index with the given id. NOTE that we do not reserve
  733. the dictionary mutex: this function is for emergency purposes like
  734. printing info of a corrupt database page! */
  735. dict_index_t*
  736. dict_index_find_on_id_low(
  737. /*======================*/
  738. /* out: index or NULL if not found from cache */
  739. dulint id) /* in: index id */
  740. {
  741. dict_table_t* table;
  742. dict_index_t* index;
  743. table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
  744. while (table) {
  745. index = dict_table_get_first_index(table);
  746. while (index) {
  747. if (0 == ut_dulint_cmp(id, index->tree->id)) {
  748. /* Found */
  749. return(index);
  750. }
  751. index = dict_table_get_next_index(index);
  752. }
  753. table = UT_LIST_GET_NEXT(table_LRU, table);
  754. }
  755. return(NULL);
  756. }
  757. /**************************************************************************
  758. Renames a table object. */
  759. ibool
  760. dict_table_rename_in_cache(
  761. /*=======================*/
  762. /* out: TRUE if success */
  763. dict_table_t* table, /* in: table */
  764. const char* new_name, /* in: new name */
  765. ibool rename_also_foreigns)/* in: in ALTER TABLE we want
  766. to preserve the original table name
  767. in constraints which reference it */
  768. {
  769. dict_foreign_t* foreign;
  770. dict_index_t* index;
  771. ulint fold;
  772. ulint old_size;
  773. char* old_name;
  774. ibool success;
  775. ulint i;
  776. ut_ad(table);
  777. #ifdef UNIV_SYNC_DEBUG
  778. ut_ad(mutex_own(&(dict_sys->mutex)));
  779. #endif /* UNIV_SYNC_DEBUG */
  780. old_size = mem_heap_get_size(table->heap);
  781. fold = ut_fold_string(new_name);
  782. /* Look for a table with the same name: error if such exists */
  783. {
  784. dict_table_t* table2;
  785. HASH_SEARCH(name_hash, dict_sys->table_hash, fold, table2,
  786. (ut_strcmp(table2->name, new_name) == 0));
  787. if (table2) {
  788. fprintf(stderr,
  789. "InnoDB: Error: dictionary cache already contains a table of name %sn",
  790.        new_name);
  791. return(FALSE);
  792. }
  793. }
  794. /* If the table is stored in a single-table tablespace, rename the
  795. .ibd file */
  796. if (table->space != 0) {
  797. if (table->dir_path_of_temp_table != NULL) {
  798. fprintf(stderr,
  799. "InnoDB: Error: trying to rename a table %s (%s) created with CREATEn"
  800. "InnoDB: TEMPORARY TABLEn", table->name, table->dir_path_of_temp_table);
  801. success = FALSE;
  802. } else {
  803. success = fil_rename_tablespace(table->name,
  804. table->space, new_name);
  805. }
  806. if (!success) {
  807. return(FALSE);
  808. }
  809. }
  810. /* Reposition the columns in the column hash table; they are hashed
  811. according to the pair (table name, column name) */
  812. for (i = 0; i < table->n_cols; i++) {
  813. dict_col_reposition_in_cache(table,
  814. dict_table_get_nth_col(table, i), new_name);
  815. }
  816. /* Remove table from the hash tables of tables */
  817. HASH_DELETE(dict_table_t, name_hash, dict_sys->table_hash,
  818. ut_fold_string(table->name), table);
  819. old_name = mem_heap_strdup(table->heap, table->name);
  820. table->name = mem_heap_strdup(table->heap, new_name);
  821. /* Add table to hash table of tables */
  822. HASH_INSERT(dict_table_t, name_hash, dict_sys->table_hash, fold,
  823.    table);
  824. dict_sys->size += (mem_heap_get_size(table->heap) - old_size);
  825. /* Update the table_name field in indexes */
  826. index = dict_table_get_first_index(table);
  827. while (index != NULL) {
  828. index->table_name = table->name;
  829. index = dict_table_get_next_index(index);
  830. }
  831. if (!rename_also_foreigns) {
  832. /* In ALTER TABLE we think of the rename table operation
  833. in the direction table -> temporary table (#sql...)
  834. as dropping the table with the old name and creating
  835. a new with the new name. Thus we kind of drop the
  836. constraints from the dictionary cache here. The foreign key
  837. constraints will be inherited to the new table from the
  838. system tables through a call of dict_load_foreigns. */
  839. /* Remove the foreign constraints from the cache */
  840. foreign = UT_LIST_GET_LAST(table->foreign_list);
  841. while (foreign != NULL) {
  842. dict_foreign_remove_from_cache(foreign);
  843. foreign = UT_LIST_GET_LAST(table->foreign_list);
  844. }
  845. /* Reset table field in referencing constraints */
  846. foreign = UT_LIST_GET_FIRST(table->referenced_list);
  847. while (foreign != NULL) {
  848. foreign->referenced_table = NULL;
  849. foreign->referenced_index = NULL;
  850. foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
  851. }
  852. /* Make the list of referencing constraints empty */
  853. UT_LIST_INIT(table->referenced_list);
  854. return(TRUE);
  855. }
  856. /* Update the table name fields in foreign constraints, and update also
  857. the constraint id of new format >= 4.0.18 constraints. Note that at
  858. this point we have already changed table->name to the new name. */
  859. foreign = UT_LIST_GET_FIRST(table->foreign_list);
  860. while (foreign != NULL) {
  861. if (ut_strlen(foreign->foreign_table_name) <
  862. ut_strlen(table->name)) {
  863. /* Allocate a longer name buffer;
  864. TODO: store buf len to save memory */
  865. foreign->foreign_table_name = mem_heap_alloc(
  866. foreign->heap,
  867. ut_strlen(table->name) + 1);
  868. }
  869. strcpy(foreign->foreign_table_name, table->name);
  870. if (strchr(foreign->id, '/')) {
  871. ulint db_len;
  872. char* old_id;
  873. /* This is a >= 4.0.18 format id */
  874. old_id = mem_strdup(foreign->id);
  875. if (ut_strlen(foreign->id) > ut_strlen(old_name)
  876. + ((sizeof dict_ibfk) - 1)
  877.     && 0 == ut_memcmp(foreign->id, old_name,
  878. ut_strlen(old_name))
  879.     && 0 == ut_memcmp(
  880. foreign->id + ut_strlen(old_name),
  881. dict_ibfk, (sizeof dict_ibfk) - 1)) {
  882. /* This is a generated >= 4.0.18 format id */
  883. if (ut_strlen(table->name) > ut_strlen(old_name)) {
  884. foreign->id = mem_heap_alloc(
  885.      foreign->heap,
  886. ut_strlen(table->name)
  887. + ut_strlen(old_id) + 1);
  888. }
  889. /* Replace the prefix 'databasename/tablename'
  890. with the new names */
  891. strcpy(foreign->id, table->name);
  892. strcat(foreign->id,
  893. old_id + ut_strlen(old_name));
  894. } else {
  895. /* This is a >= 4.0.18 format id where the user
  896. gave the id name */
  897. db_len = dict_get_db_name_len(table->name) + 1;
  898. if (dict_get_db_name_len(table->name)
  899.          > dict_get_db_name_len(foreign->id)) {
  900. foreign->id = mem_heap_alloc(
  901.      foreign->heap,
  902.        db_len + ut_strlen(old_id) + 1);
  903. }
  904. /* Replace the database prefix in id with the
  905. one from table->name */
  906. ut_memcpy(foreign->id, table->name, db_len);
  907. strcpy(foreign->id + db_len,
  908. dict_remove_db_name(old_id));
  909. }
  910. mem_free(old_id);
  911. }
  912. foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
  913. }
  914. foreign = UT_LIST_GET_FIRST(table->referenced_list);
  915. while (foreign != NULL) {
  916. if (ut_strlen(foreign->referenced_table_name) <
  917. ut_strlen(table->name)) {
  918. /* Allocate a longer name buffer;
  919. TODO: store buf len to save memory */
  920. foreign->referenced_table_name = mem_heap_alloc(
  921. foreign->heap,
  922. ut_strlen(table->name) + 1);
  923. }
  924. strcpy(foreign->referenced_table_name, table->name);
  925. foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
  926. }
  927. return(TRUE);
  928. }
  929. /**************************************************************************
  930. Change the id of a table object in the dictionary cache. This is used in
  931. DISCARD TABLESPACE. */
  932. void
  933. dict_table_change_id_in_cache(
  934. /*==========================*/
  935. dict_table_t* table, /* in: table object already in cache */
  936. dulint new_id) /* in: new id to set */
  937. {
  938. ut_ad(table);
  939. #ifdef UNIV_SYNC_DEBUG
  940. ut_ad(mutex_own(&(dict_sys->mutex)));
  941. #endif /* UNIV_SYNC_DEBUG */
  942. ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
  943. /* Remove the table from the hash table of id's */
  944. HASH_DELETE(dict_table_t, id_hash, dict_sys->table_id_hash,
  945. ut_fold_dulint(table->id), table);
  946. table->id = new_id;
  947. /* Add the table back to the hash table */
  948. HASH_INSERT(dict_table_t, id_hash, dict_sys->table_id_hash,
  949. ut_fold_dulint(table->id), table);
  950. }
  951. /**************************************************************************
  952. Removes a table object from the dictionary cache. */
  953. void
  954. dict_table_remove_from_cache(
  955. /*=========================*/
  956. dict_table_t* table) /* in, own: table */
  957. {
  958. dict_foreign_t* foreign;
  959. dict_index_t* index;
  960. ulint size;
  961. ulint i;
  962. ut_ad(table);
  963. #ifdef UNIV_SYNC_DEBUG
  964. ut_ad(mutex_own(&(dict_sys->mutex)));
  965. #endif /* UNIV_SYNC_DEBUG */
  966. ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
  967. #if 0
  968. fputs("Removing table ", stderr);
  969. ut_print_name(stderr, table->name, ULINT_UNDEFINED);
  970. fputs(" from dictionary cachen", stderr);
  971. #endif
  972. /* Remove the foreign constraints from the cache */
  973. foreign = UT_LIST_GET_LAST(table->foreign_list);
  974. while (foreign != NULL) {
  975. dict_foreign_remove_from_cache(foreign);
  976. foreign = UT_LIST_GET_LAST(table->foreign_list);
  977. }
  978. /* Reset table field in referencing constraints */
  979. foreign = UT_LIST_GET_FIRST(table->referenced_list);
  980. while (foreign != NULL) {
  981. foreign->referenced_table = NULL;
  982. foreign->referenced_index = NULL;
  983. foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
  984. }
  985. /* Remove the indexes from the cache */
  986. index = UT_LIST_GET_LAST(table->indexes);
  987. while (index != NULL) {
  988. dict_index_remove_from_cache(table, index);
  989. index = UT_LIST_GET_LAST(table->indexes);
  990. }
  991. /* Remove the columns of the table from the cache */
  992. for (i = 0; i < table->n_cols; i++) {
  993. dict_col_remove_from_cache(table,
  994.    dict_table_get_nth_col(table, i));
  995. }
  996. /* Remove table from the hash tables of tables */
  997. HASH_DELETE(dict_table_t, name_hash, dict_sys->table_hash,
  998. ut_fold_string(table->name), table);
  999. HASH_DELETE(dict_table_t, id_hash, dict_sys->table_id_hash,
  1000. ut_fold_dulint(table->id), table);
  1001. /* Remove table from LRU list of tables */
  1002. UT_LIST_REMOVE(table_LRU, dict_sys->table_LRU, table);
  1003. mutex_free(&(table->autoinc_mutex));
  1004. size = mem_heap_get_size(table->heap);
  1005. ut_ad(dict_sys->size >= size);
  1006. dict_sys->size -= size;
  1007. mem_heap_free(table->heap);
  1008. }
  1009. /**************************************************************************
  1010. Frees tables from the end of table_LRU if the dictionary cache occupies
  1011. too much space. Currently not used! */
  1012. void
  1013. dict_table_LRU_trim(void)
  1014. /*=====================*/
  1015. {
  1016. dict_table_t* table;
  1017. dict_table_t* prev_table;
  1018. ut_error;
  1019. #ifdef UNIV_SYNC_DEBUG
  1020. ut_ad(mutex_own(&(dict_sys->mutex)));
  1021. #endif /* UNIV_SYNC_DEBUG */
  1022. table = UT_LIST_GET_LAST(dict_sys->table_LRU);
  1023. while (table && (dict_sys->size >
  1024.  buf_pool_get_max_size() / DICT_POOL_PER_VARYING)) {
  1025. prev_table = UT_LIST_GET_PREV(table_LRU, table);
  1026. if (table->mem_fix == 0) {
  1027. dict_table_remove_from_cache(table);
  1028. }
  1029. table = prev_table;
  1030. }
  1031. }
  1032. /**************************************************************************
  1033. Adds a column to the data dictionary hash table. */
  1034. static
  1035. void
  1036. dict_col_add_to_cache(
  1037. /*==================*/
  1038. dict_table_t* table, /* in: table */
  1039. dict_col_t* col) /* in: column */
  1040. {
  1041. ulint fold;
  1042. ut_ad(table && col);
  1043. #ifdef UNIV_SYNC_DEBUG
  1044. ut_ad(mutex_own(&(dict_sys->mutex)));
  1045. #endif /* UNIV_SYNC_DEBUG */
  1046. ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
  1047. fold = ut_fold_ulint_pair(ut_fold_string(table->name),
  1048.   ut_fold_string(col->name));
  1049. /* Look for a column with same table name and column name: error */
  1050. {
  1051. dict_col_t* col2;
  1052. HASH_SEARCH(hash, dict_sys->col_hash, fold, col2,
  1053. (ut_strcmp(col->name, col2->name) == 0)
  1054. && (ut_strcmp((col2->table)->name, table->name)
  1055. == 0));  
  1056. ut_a(col2 == NULL);
  1057. }
  1058. HASH_INSERT(dict_col_t, hash, dict_sys->col_hash, fold, col);
  1059. }
  1060. /**************************************************************************
  1061. Removes a column from the data dictionary hash table. */
  1062. static
  1063. void
  1064. dict_col_remove_from_cache(
  1065. /*=======================*/
  1066. dict_table_t* table, /* in: table */
  1067. dict_col_t* col) /* in: column */
  1068. {
  1069. ulint fold;
  1070. ut_ad(table && col);
  1071. #ifdef UNIV_SYNC_DEBUG
  1072. ut_ad(mutex_own(&(dict_sys->mutex)));
  1073. #endif /* UNIV_SYNC_DEBUG */
  1074. ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
  1075. fold = ut_fold_ulint_pair(ut_fold_string(table->name),
  1076.   ut_fold_string(col->name));
  1077. HASH_DELETE(dict_col_t, hash, dict_sys->col_hash, fold, col);
  1078. }
  1079. /**************************************************************************
  1080. Repositions a column in the data dictionary hash table when the table name
  1081. changes. */
  1082. static
  1083. void
  1084. dict_col_reposition_in_cache(
  1085. /*=========================*/
  1086. dict_table_t* table, /* in: table */
  1087. dict_col_t* col, /* in: column */
  1088. const char* new_name) /* in: new table name */
  1089. {
  1090. ulint fold;
  1091. ut_ad(table && col);
  1092. #ifdef UNIV_SYNC_DEBUG
  1093. ut_ad(mutex_own(&(dict_sys->mutex)));
  1094. #endif /* UNIV_SYNC_DEBUG */
  1095. ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
  1096. fold = ut_fold_ulint_pair(ut_fold_string(table->name),
  1097.   ut_fold_string(col->name));
  1098. HASH_DELETE(dict_col_t, hash, dict_sys->col_hash, fold, col);
  1099. fold = ut_fold_ulint_pair(ut_fold_string(new_name),
  1100.   ut_fold_string(col->name));
  1101.   
  1102. HASH_INSERT(dict_col_t, hash, dict_sys->col_hash, fold, col);
  1103. }
  1104. /**************************************************************************
  1105. Adds an index to the dictionary cache. */
  1106. ibool
  1107. dict_index_add_to_cache(
  1108. /*====================*/
  1109. /* out: TRUE if success */
  1110. dict_table_t* table, /* in: table on which the index is */
  1111. dict_index_t* index) /* in, own: index; NOTE! The index memory
  1112. object is freed in this function! */
  1113. {
  1114. dict_index_t* new_index;
  1115. dict_tree_t* tree;
  1116. dict_table_t* cluster;
  1117. dict_field_t* field;
  1118. ulint n_ord;
  1119. ibool success;
  1120. ulint i;
  1121. ut_ad(index);
  1122. #ifdef UNIV_SYNC_DEBUG
  1123. ut_ad(mutex_own(&(dict_sys->mutex)));
  1124. #endif /* UNIV_SYNC_DEBUG */
  1125. ut_ad(index->n_def == index->n_fields);
  1126. ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
  1127. ut_ad(mem_heap_validate(index->heap));
  1128. {
  1129. dict_index_t* index2;
  1130. index2 = UT_LIST_GET_FIRST(table->indexes);
  1131. while (index2 != NULL) {
  1132. ut_ad(ut_strcmp(index->name, index2->name) != 0);
  1133. index2 = UT_LIST_GET_NEXT(indexes, index2);
  1134. }
  1135. ut_a(UT_LIST_GET_LEN(table->indexes) == 0
  1136.        || (index->type & DICT_CLUSTERED) == 0);
  1137. }
  1138. success = dict_index_find_cols(table, index);
  1139. if (!success) {
  1140. dict_mem_index_free(index);
  1141. return(FALSE);
  1142. }
  1143. /* Build the cache internal representation of the index,
  1144. containing also the added system fields */
  1145. if (index->type & DICT_CLUSTERED) {
  1146. new_index = dict_index_build_internal_clust(table, index);
  1147. } else {
  1148. new_index = dict_index_build_internal_non_clust(table, index);
  1149. }
  1150. new_index->search_info = btr_search_info_create(new_index->heap);
  1151. /* Set the n_fields value in new_index to the actual defined
  1152. number of fields in the cache internal representation */
  1153. new_index->n_fields = new_index->n_def;
  1154. /* Add the new index as the last index for the table */
  1155. UT_LIST_ADD_LAST(indexes, table->indexes, new_index);
  1156. new_index->table = table;
  1157. new_index->table_name = table->name;
  1158. /* Increment the ord_part counts in columns which are ordering */
  1159. if (index->type & DICT_UNIVERSAL) {
  1160. n_ord = new_index->n_fields;
  1161. } else {
  1162. n_ord = dict_index_get_n_unique(new_index);
  1163. }
  1164. for (i = 0; i < n_ord; i++) {
  1165. field = dict_index_get_nth_field(new_index, i);
  1166. dict_field_get_col(field)->ord_part++;
  1167. }
  1168. if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
  1169. /* The index tree is found from the cluster object */
  1170.     
  1171. cluster = dict_table_get_low(table->cluster_name);
  1172. tree = dict_index_get_tree(
  1173. UT_LIST_GET_FIRST(cluster->indexes));
  1174. new_index->tree = tree;
  1175. new_index->page_no = tree->page;
  1176. } else {
  1177. /* Create an index tree memory object for the index */
  1178. tree = dict_tree_create(new_index);
  1179. ut_ad(tree);
  1180. new_index->tree = tree;
  1181. }
  1182. if (!(new_index->type & DICT_UNIVERSAL)) {
  1183. new_index->stat_n_diff_key_vals =
  1184. mem_heap_alloc(new_index->heap,
  1185. (1 + dict_index_get_n_unique(new_index))
  1186. * sizeof(ib_longlong));
  1187. /* Give some sensible values to stat_n_... in case we do
  1188. not calculate statistics quickly enough */
  1189. for (i = 0; i <= dict_index_get_n_unique(new_index); i++) {
  1190. new_index->stat_n_diff_key_vals[i] = 100;
  1191. }
  1192. }
  1193. /* Add the index to the list of indexes stored in the tree */
  1194. UT_LIST_ADD_LAST(tree_indexes, tree->tree_indexes, new_index); 
  1195. /* If the dictionary cache grows too big, trim the table LRU list */
  1196. dict_sys->size += mem_heap_get_size(new_index->heap);
  1197. /* dict_table_LRU_trim(); */
  1198. dict_mem_index_free(index);
  1199. return(TRUE);
  1200. }
  1201. /**************************************************************************
  1202. Removes an index from the dictionary cache. */
  1203. static
  1204. void
  1205. dict_index_remove_from_cache(
  1206. /*=========================*/
  1207. dict_table_t* table, /* in: table */
  1208. dict_index_t* index) /* in, own: index */
  1209. {
  1210. dict_field_t* field;
  1211. ulint size;
  1212. ulint i;
  1213. ut_ad(table && index);
  1214. ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
  1215. ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
  1216. #ifdef UNIV_SYNC_DEBUG
  1217. ut_ad(mutex_own(&(dict_sys->mutex)));
  1218. #endif /* UNIV_SYNC_DEBUG */
  1219. ut_ad(UT_LIST_GET_LEN((index->tree)->tree_indexes) == 1);
  1220. dict_tree_free(index->tree);
  1221. /* Decrement the ord_part counts in columns which are ordering */
  1222. for (i = 0; i < dict_index_get_n_unique(index); i++) {
  1223. field = dict_index_get_nth_field(index, i);
  1224. ut_ad(dict_field_get_col(field)->ord_part > 0);
  1225. (dict_field_get_col(field)->ord_part)--;
  1226. }
  1227. /* Remove the index from the list of indexes of the table */
  1228. UT_LIST_REMOVE(indexes, table->indexes, index);
  1229. size = mem_heap_get_size(index->heap);
  1230. ut_ad(dict_sys->size >= size);
  1231. dict_sys->size -= size;
  1232. mem_heap_free(index->heap);
  1233. }
  1234. /***********************************************************************
  1235. Tries to find column names for the index in the column hash table and
  1236. sets the col field of the index. */
  1237. static
  1238. ibool
  1239. dict_index_find_cols(
  1240. /*=================*/
  1241. /* out: TRUE if success */
  1242. dict_table_t* table, /* in: table */
  1243. dict_index_t* index) /* in: index */
  1244. {
  1245. dict_col_t* col;
  1246. dict_field_t* field;
  1247. ulint fold;
  1248. ulint i;
  1249. ut_ad(table && index);
  1250. ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
  1251. #ifdef UNIV_SYNC_DEBUG
  1252. ut_ad(mutex_own(&(dict_sys->mutex)));
  1253. #endif /* UNIV_SYNC_DEBUG */
  1254. for (i = 0; i < index->n_fields; i++) {
  1255. field = dict_index_get_nth_field(index, i);
  1256. fold = ut_fold_ulint_pair(ut_fold_string(table->name),
  1257.           ut_fold_string(field->name));
  1258. HASH_SEARCH(hash, dict_sys->col_hash, fold, col,
  1259. (ut_strcmp(col->name, field->name) == 0)
  1260. && (ut_strcmp((col->table)->name, table->name)
  1261. == 0));  
  1262. if (col == NULL) {
  1263.   return(FALSE);
  1264. } else {
  1265. field->col = col;
  1266. }
  1267. }
  1268. return(TRUE);
  1269. }
  1270. /***********************************************************************
  1271. Adds a column to index. */
  1272. UNIV_INLINE
  1273. void
  1274. dict_index_add_col(
  1275. /*===============*/
  1276. dict_index_t* index, /* in: index */
  1277. dict_col_t* col, /* in: column */
  1278. ulint order, /* in: order criterion */
  1279. ulint prefix_len) /* in: column prefix length */
  1280. {
  1281. dict_field_t* field;
  1282. dict_mem_index_add_field(index, col->name, order, prefix_len);
  1283. field = dict_index_get_nth_field(index, index->n_def - 1);
  1284. field->col = col;
  1285. }
  1286. /***********************************************************************
  1287. Copies fields contained in index2 to index1. */
  1288. static
  1289. void
  1290. dict_index_copy(
  1291. /*============*/
  1292. dict_index_t* index1, /* in: index to copy to */
  1293. dict_index_t* index2, /* in: index to copy from */
  1294. ulint start, /* in: first position to copy */
  1295. ulint end) /* in: last position to copy */
  1296. {
  1297. dict_field_t* field;
  1298. ulint i;
  1299. /* Copy fields contained in index2 */
  1300. for (i = start; i < end; i++) {
  1301. field = dict_index_get_nth_field(index2, i);
  1302. dict_index_add_col(index1, field->col, field->order,
  1303.       field->prefix_len);
  1304. }
  1305. }
  1306. /***********************************************************************
  1307. Copies types of fields contained in index to tuple. */
  1308. void
  1309. dict_index_copy_types(
  1310. /*==================*/
  1311. dtuple_t* tuple, /* in: data tuple */
  1312. dict_index_t* index, /* in: index */
  1313. ulint n_fields) /* in: number of field types to copy */
  1314. {
  1315. dtype_t* dfield_type;
  1316. dtype_t* type;
  1317. ulint i;
  1318. if (index->type & DICT_UNIVERSAL) {
  1319. dtuple_set_types_binary(tuple, n_fields);
  1320. return;
  1321. }
  1322. for (i = 0; i < n_fields; i++) {
  1323. dfield_type = dfield_get_type(dtuple_get_nth_field(tuple, i));
  1324. type = dict_col_get_type(dict_field_get_col(
  1325. dict_index_get_nth_field(index, i)));
  1326. *dfield_type = *type;
  1327. }
  1328. }
  1329. /***********************************************************************
  1330. Copies types of columns contained in table to tuple. */
  1331. void
  1332. dict_table_copy_types(
  1333. /*==================*/
  1334. dtuple_t* tuple, /* in: data tuple */
  1335. dict_table_t* table) /* in: index */
  1336. {
  1337. dtype_t* dfield_type;
  1338. dtype_t* type;
  1339. ulint i;
  1340. ut_ad(!(table->type & DICT_UNIVERSAL));
  1341. for (i = 0; i < dtuple_get_n_fields(tuple); i++) {
  1342. dfield_type = dfield_get_type(dtuple_get_nth_field(tuple, i));
  1343. type = dict_col_get_type(dict_table_get_nth_col(table, i));
  1344. *dfield_type = *type;
  1345. }
  1346. }
  1347. /***********************************************************************
  1348. Builds the internal dictionary cache representation for a clustered
  1349. index, containing also system fields not defined by the user. */
  1350. static
  1351. dict_index_t*
  1352. dict_index_build_internal_clust(
  1353. /*============================*/
  1354. /* out, own: the internal representation
  1355. of the clustered index */
  1356. dict_table_t* table, /* in: table */
  1357. dict_index_t* index) /* in: user representation of a clustered
  1358. index */
  1359. {
  1360. dict_index_t* new_index;
  1361. dict_field_t* field;
  1362. dict_col_t* col;
  1363. ulint fixed_size;
  1364. ulint trx_id_pos;
  1365. ulint i;
  1366. ut_ad(table && index);
  1367. ut_ad(index->type & DICT_CLUSTERED);
  1368. #ifdef UNIV_SYNC_DEBUG
  1369. ut_ad(mutex_own(&(dict_sys->mutex)));
  1370. #endif /* UNIV_SYNC_DEBUG */
  1371. ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
  1372. /* Create a new index object with certainly enough fields */
  1373. new_index = dict_mem_index_create(table->name,
  1374.      index->name,
  1375.      table->space,
  1376.      index->type,
  1377.      index->n_fields + table->n_cols);
  1378. /* Copy other relevant data from the old index struct to the new
  1379. struct: it inherits the values */
  1380. new_index->n_user_defined_cols = index->n_fields;
  1381. new_index->id = index->id;
  1382. new_index->page_no = index->page_no;
  1383. if (table->type != DICT_TABLE_ORDINARY) {
  1384. /* The index is mixed: copy common key prefix fields */
  1385. dict_index_copy(new_index, index, 0, table->mix_len);
  1386. /* Add the mix id column */
  1387. dict_index_add_col(new_index,
  1388.   dict_table_get_sys_col(table, DATA_MIX_ID), 0, 0);
  1389. /* Copy the rest of fields */
  1390. dict_index_copy(new_index, index, table->mix_len,
  1391. index->n_fields);
  1392. } else {
  1393. /* Copy the fields of index */
  1394. dict_index_copy(new_index, index, 0, index->n_fields);
  1395. }
  1396. if (index->type & DICT_UNIVERSAL) {
  1397. /* No fixed number of fields determines an entry uniquely */
  1398. new_index->n_uniq = ULINT_MAX;
  1399. } else if (index->type & DICT_UNIQUE) {
  1400. /* Only the fields defined so far are needed to identify
  1401. the index entry uniquely */
  1402. new_index->n_uniq = new_index->n_def;
  1403. } else {
  1404. /* Also the row id is needed to identify the entry */
  1405. new_index->n_uniq = 1 + new_index->n_def;
  1406. }
  1407. new_index->trx_id_offset = 0;
  1408. if (!(index->type & DICT_IBUF)) {
  1409. /* Add system columns, trx id first */
  1410. trx_id_pos = new_index->n_def;
  1411. ut_ad(DATA_ROW_ID == 0);
  1412. ut_ad(DATA_TRX_ID == 1);
  1413. ut_ad(DATA_ROLL_PTR == 2);
  1414. if (!(index->type & DICT_UNIQUE)) {
  1415. dict_index_add_col(new_index,
  1416.    dict_table_get_sys_col(table, DATA_ROW_ID), 0, 0);
  1417. trx_id_pos++;
  1418. }
  1419. dict_index_add_col(new_index,
  1420.    dict_table_get_sys_col(table, DATA_TRX_ID), 0, 0);
  1421. dict_index_add_col(new_index,
  1422.    dict_table_get_sys_col(table, DATA_ROLL_PTR), 0, 0);
  1423. for (i = 0; i < trx_id_pos; i++) {
  1424. fixed_size = dtype_get_fixed_size(
  1425. dict_index_get_nth_type(new_index, i));
  1426. if (fixed_size == 0) {
  1427. new_index->trx_id_offset = 0;
  1428. break;
  1429. }
  1430. if (dict_index_get_nth_field(new_index, i)->prefix_len
  1431.     > 0) {
  1432. new_index->trx_id_offset = 0;
  1433. break;
  1434. }
  1435. new_index->trx_id_offset += fixed_size;
  1436. }
  1437. }
  1438. /* Set auxiliary variables in table columns as undefined */
  1439. for (i = 0; i < table->n_cols; i++) {
  1440. col = dict_table_get_nth_col(table, i);
  1441. col->aux = ULINT_UNDEFINED;
  1442. }
  1443. /* Mark with 0 the table columns already contained in new_index */
  1444. for (i = 0; i < new_index->n_def; i++) {
  1445. field = dict_index_get_nth_field(new_index, i);
  1446. /* If there is only a prefix of the column in the index
  1447. field, do not mark the column as contained in the index */
  1448. if (field->prefix_len == 0) {
  1449.         field->col->aux = 0;
  1450. }
  1451. }
  1452. /* Add to new_index non-system columns of table not yet included
  1453. there */
  1454. for (i = 0; i < table->n_cols - DATA_N_SYS_COLS; i++) {
  1455. col = dict_table_get_nth_col(table, i);
  1456. ut_ad(col->type.mtype != DATA_SYS);
  1457. if (col->aux == ULINT_UNDEFINED) {
  1458. dict_index_add_col(new_index, col, 0, 0);
  1459. }
  1460. }
  1461. ut_ad((index->type & DICT_IBUF)
  1462. || (UT_LIST_GET_LEN(table->indexes) == 0));
  1463. /* Store to the column structs the position of the table columns
  1464. in the clustered index */
  1465. for (i = 0; i < new_index->n_def; i++) {
  1466. field = dict_index_get_nth_field(new_index, i);
  1467. if (field->prefix_len == 0) {
  1468.         field->col->clust_pos = i;
  1469. }
  1470. }
  1471. new_index->cached = TRUE;
  1472. return(new_index);
  1473. }
  1474. /***********************************************************************
  1475. Builds the internal dictionary cache representation for a non-clustered
  1476. index, containing also system fields not defined by the user. */
  1477. static
  1478. dict_index_t*
  1479. dict_index_build_internal_non_clust(
  1480. /*================================*/
  1481. /* out, own: the internal representation
  1482. of the non-clustered index */
  1483. dict_table_t* table, /* in: table */
  1484. dict_index_t* index) /* in: user representation of a non-clustered
  1485. index */
  1486. {
  1487. dict_field_t* field;
  1488. dict_index_t* new_index;
  1489. dict_index_t* clust_index;
  1490. ulint i;
  1491. ut_ad(table && index);
  1492. ut_ad(0 == (index->type & DICT_CLUSTERED));
  1493. #ifdef UNIV_SYNC_DEBUG
  1494. ut_ad(mutex_own(&(dict_sys->mutex)));
  1495. #endif /* UNIV_SYNC_DEBUG */
  1496. ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
  1497. /* The clustered index should be the first in the list of indexes */
  1498. clust_index = UT_LIST_GET_FIRST(table->indexes);
  1499. ut_ad(clust_index);
  1500. ut_ad(clust_index->type & DICT_CLUSTERED);
  1501. ut_ad(!(clust_index->type & DICT_UNIVERSAL));
  1502. /* Create a new index */
  1503. new_index = dict_mem_index_create(table->name,
  1504.      index->name,
  1505.      index->space,
  1506.      index->type,
  1507.      index->n_fields
  1508.      + 1 + clust_index->n_uniq);
  1509. /* Copy other relevant data from the old index
  1510. struct to the new struct: it inherits the values */
  1511. new_index->n_user_defined_cols = index->n_fields;
  1512. new_index->id = index->id;
  1513. new_index->page_no = index->page_no;
  1514. /* Copy fields from index to new_index */
  1515. dict_index_copy(new_index, index, 0, index->n_fields);
  1516. /* Set the auxiliary variables in the clust_index unique columns
  1517. as undefined */
  1518. for (i = 0; i < clust_index->n_uniq; i++) {
  1519. field = dict_index_get_nth_field(clust_index, i);
  1520. field->col->aux = ULINT_UNDEFINED;
  1521. }
  1522. /* Mark with 0 table columns already contained in new_index */
  1523. for (i = 0; i < new_index->n_def; i++) {
  1524. field = dict_index_get_nth_field(new_index, i);
  1525. /* If there is only a prefix of the column in the index
  1526. field, do not mark the column as contained in the index */
  1527. if (field->prefix_len == 0) {
  1528.         field->col->aux = 0;
  1529. }
  1530. }
  1531. /* Add to new_index the columns necessary to determine the clustered
  1532. index entry uniquely */
  1533. for (i = 0; i < clust_index->n_uniq; i++) {
  1534. field = dict_index_get_nth_field(clust_index, i);
  1535. if (field->col->aux == ULINT_UNDEFINED) {
  1536. dict_index_add_col(new_index, field->col, 0,
  1537.       field->prefix_len);
  1538. }
  1539. }
  1540. if ((index->type) & DICT_UNIQUE) {
  1541. new_index->n_uniq = index->n_fields;
  1542. } else {
  1543. new_index->n_uniq = new_index->n_def;
  1544. }
  1545. /* Set the n_fields value in new_index to the actual defined
  1546. number of fields */
  1547. new_index->n_fields = new_index->n_def;
  1548. new_index->cached = TRUE;
  1549. return(new_index);
  1550. }
  1551. /*====================== FOREIGN KEY PROCESSING ========================*/
  1552. /*************************************************************************
  1553. Checks if a table is referenced by foreign keys. */
  1554. ibool
  1555. dict_table_referenced_by_foreign_key(
  1556. /*=================================*/
  1557. /* out: TRUE if table is referenced by a
  1558. foreign key */
  1559. dict_table_t* table) /* in: InnoDB table */
  1560. {
  1561. if (UT_LIST_GET_LEN(table->referenced_list) > 0) {
  1562. return(TRUE);
  1563. }
  1564. return(FALSE);
  1565. }
  1566. /*************************************************************************
  1567. Frees a foreign key struct. */
  1568. static
  1569. void
  1570. dict_foreign_free(
  1571. /*==============*/
  1572. dict_foreign_t* foreign) /* in, own: foreign key struct */
  1573. {
  1574. mem_heap_free(foreign->heap);
  1575. }
  1576. /**************************************************************************
  1577. Removes a foreign constraint struct from the dictionary cache. */
  1578. static
  1579. void
  1580. dict_foreign_remove_from_cache(
  1581. /*===========================*/
  1582. dict_foreign_t* foreign) /* in, own: foreign constraint */
  1583. {
  1584. #ifdef UNIV_SYNC_DEBUG
  1585. ut_ad(mutex_own(&(dict_sys->mutex)));
  1586. #endif /* UNIV_SYNC_DEBUG */
  1587. ut_a(foreign);
  1588. if (foreign->referenced_table) {
  1589. UT_LIST_REMOVE(referenced_list,
  1590. foreign->referenced_table->referenced_list, foreign);
  1591. }
  1592. if (foreign->foreign_table) {
  1593. UT_LIST_REMOVE(foreign_list,
  1594. foreign->foreign_table->foreign_list, foreign);
  1595. }
  1596. dict_foreign_free(foreign);
  1597. }
  1598. /**************************************************************************
  1599. Looks for the foreign constraint from the foreign and referenced lists
  1600. of a table. */
  1601. static
  1602. dict_foreign_t*
  1603. dict_foreign_find(
  1604. /*==============*/
  1605. /* out: foreign constraint */
  1606. dict_table_t* table, /* in: table object */
  1607. const char* id) /* in: foreign constraint id */
  1608. {
  1609. dict_foreign_t* foreign;
  1610. #ifdef UNIV_SYNC_DEBUG
  1611. ut_ad(mutex_own(&(dict_sys->mutex)));
  1612. #endif /* UNIV_SYNC_DEBUG */
  1613. foreign = UT_LIST_GET_FIRST(table->foreign_list);
  1614. while (foreign) {
  1615. if (ut_strcmp(id, foreign->id) == 0) {
  1616. return(foreign);
  1617. }
  1618. foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
  1619. }
  1620. foreign = UT_LIST_GET_FIRST(table->referenced_list);
  1621. while (foreign) {
  1622. if (ut_strcmp(id, foreign->id) == 0) {
  1623. return(foreign);
  1624. }
  1625. foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
  1626. }
  1627. return(NULL);
  1628. }
  1629. /*************************************************************************
  1630. Tries to find an index whose first fields are the columns in the array,
  1631. in the same order. */
  1632. static
  1633. dict_index_t*
  1634. dict_foreign_find_index(
  1635. /*====================*/
  1636. /* out: matching index, NULL if not found */
  1637. dict_table_t* table, /* in: table */
  1638. const char** columns,/* in: array of column names */
  1639. ulint n_cols, /* in: number of columns */
  1640. dict_index_t* types_idx)/* in: NULL or an index to whose types the
  1641. column types must match */
  1642. {
  1643. dict_index_t* index;
  1644. const char* col_name;
  1645. ulint i;
  1646. index = dict_table_get_first_index(table);
  1647. while (index != NULL) {
  1648. if (dict_index_get_n_fields(index) >= n_cols) {
  1649. for (i = 0; i < n_cols; i++) {
  1650. col_name = dict_index_get_nth_field(index, i)
  1651. ->col->name;
  1652. if (dict_index_get_nth_field(index, i)
  1653. ->prefix_len != 0) {
  1654. /* We do not accept column prefix
  1655. indexes here */
  1656. break;
  1657. }
  1658. if (0 != innobase_strcasecmp(columns[i],
  1659. col_name)) {
  1660.    break;
  1661. }
  1662. if (types_idx && !cmp_types_are_equal(
  1663.      dict_index_get_nth_type(index, i),
  1664.      dict_index_get_nth_type(types_idx, i))) {
  1665.    break;
  1666. }
  1667. }
  1668. if (i == n_cols) {
  1669. /* We found a matching index */
  1670. return(index);
  1671. }
  1672. }
  1673. index = dict_table_get_next_index(index);
  1674. }
  1675. return(NULL);
  1676. }
  1677. /**************************************************************************
  1678. Report an error in a foreign key definition. */
  1679. static
  1680. void
  1681. dict_foreign_error_report_low(
  1682. /*==========================*/
  1683. FILE* file, /* in: output stream */
  1684. const char* name) /* in: table name */
  1685. {
  1686. rewind(file);
  1687. ut_print_timestamp(file);
  1688. fprintf(file, " Error in foreign key constraint of table %s:n",
  1689. name);
  1690. }
  1691. /**************************************************************************
  1692. Report an error in a foreign key definition. */
  1693. static
  1694. void
  1695. dict_foreign_error_report(
  1696. /*======================*/
  1697. FILE* file, /* in: output stream */
  1698. dict_foreign_t* fk, /* in: foreign key constraint */
  1699. const char* msg) /* in: the error message */
  1700. {
  1701. mutex_enter(&dict_foreign_err_mutex);
  1702. dict_foreign_error_report_low(file, fk->foreign_table_name);
  1703. fputs(msg, file);
  1704. fputs(" Constraint:n", file);
  1705. dict_print_info_on_foreign_key_in_create_format(file, NULL, fk);
  1706. if (fk->foreign_index) {
  1707. fputs("nThe index in the foreign key in table is ", file);
  1708. ut_print_name(file, NULL, fk->foreign_index->name);
  1709. fputs(
  1710. "nSee http://dev.mysql.com/doc/mysql/en/InnoDB_foreign_key_constraints.htmln"
  1711. "for correct foreign key definition.n",
  1712. file);
  1713. }
  1714. mutex_exit(&dict_foreign_err_mutex);
  1715. }
  1716. /**************************************************************************
  1717. Adds a foreign key constraint object to the dictionary cache. May free
  1718. the object if there already is an object with the same identifier in.
  1719. At least one of the foreign table and the referenced table must already
  1720. be in the dictionary cache! */
  1721. ulint
  1722. dict_foreign_add_to_cache(
  1723. /*======================*/
  1724. /* out: DB_SUCCESS or error code */
  1725. dict_foreign_t* foreign, /* in, own: foreign key constraint */
  1726. ibool check_types) /* in: TRUE=check type compatibility */
  1727. {
  1728. dict_table_t* for_table;
  1729. dict_table_t* ref_table;
  1730. dict_foreign_t* for_in_cache = NULL;
  1731. dict_index_t* index;
  1732. ibool added_to_referenced_list= FALSE;
  1733. FILE* ef  = dict_foreign_err_file;
  1734. #ifdef UNIV_SYNC_DEBUG
  1735. ut_ad(mutex_own(&(dict_sys->mutex)));
  1736. #endif /* UNIV_SYNC_DEBUG */
  1737. for_table = dict_table_check_if_in_cache_low(
  1738. foreign->foreign_table_name);
  1739. ref_table = dict_table_check_if_in_cache_low(
  1740. foreign->referenced_table_name);
  1741. ut_a(for_table || ref_table);
  1742. if (for_table) {
  1743. for_in_cache = dict_foreign_find(for_table, foreign->id);
  1744. }
  1745. if (!for_in_cache && ref_table) {
  1746. for_in_cache = dict_foreign_find(ref_table, foreign->id);
  1747. }
  1748. if (for_in_cache) {
  1749. /* Free the foreign object */
  1750. mem_heap_free(foreign->heap);
  1751. } else {
  1752. for_in_cache = foreign;
  1753. }
  1754. if (for_in_cache->referenced_table == NULL && ref_table) {
  1755. dict_index_t* types_idx;
  1756. if (check_types) {
  1757. types_idx = for_in_cache->foreign_index;
  1758. } else {
  1759. types_idx = NULL;
  1760. }
  1761. index = dict_foreign_find_index(ref_table,
  1762. (const char**) for_in_cache->referenced_col_names,
  1763. for_in_cache->n_fields,
  1764. types_idx);
  1765. if (index == NULL) {
  1766. dict_foreign_error_report(ef, for_in_cache,
  1767. "there is no index in referenced table which would containn"
  1768. "the columns as the first columns, or the data types in then"
  1769. "referenced table do not match to the ones in table.");
  1770. if (for_in_cache == foreign) {
  1771. mem_heap_free(foreign->heap);
  1772. }
  1773.      return(DB_CANNOT_ADD_CONSTRAINT);
  1774. }
  1775. for_in_cache->referenced_table = ref_table;
  1776. for_in_cache->referenced_index = index;
  1777. UT_LIST_ADD_LAST(referenced_list,
  1778. ref_table->referenced_list,
  1779. for_in_cache);
  1780. added_to_referenced_list = TRUE;
  1781. }
  1782. if (for_in_cache->foreign_table == NULL && for_table) {
  1783. dict_index_t* types_idx;
  1784. if (check_types) {
  1785. types_idx = for_in_cache->referenced_index;
  1786. } else {
  1787. types_idx = NULL;
  1788. }
  1789. index = dict_foreign_find_index(for_table,
  1790. (const char**) for_in_cache->foreign_col_names,
  1791. for_in_cache->n_fields,
  1792. types_idx);
  1793. if (index == NULL) {
  1794. dict_foreign_error_report(ef, for_in_cache,
  1795. "there is no index in the table which would containn"
  1796. "the columns as the first columns, or the data types in then"
  1797. "table do not match to the ones in the referenced table.");
  1798. if (for_in_cache == foreign) {
  1799. if (added_to_referenced_list) {
  1800. UT_LIST_REMOVE(referenced_list,
  1801. ref_table->referenced_list,
  1802. for_in_cache);
  1803. }
  1804. mem_heap_free(foreign->heap);
  1805. }
  1806.      return(DB_CANNOT_ADD_CONSTRAINT);
  1807. }
  1808. for_in_cache->foreign_table = for_table;
  1809. for_in_cache->foreign_index = index;
  1810. UT_LIST_ADD_LAST(foreign_list,
  1811. for_table->foreign_list,
  1812. for_in_cache);
  1813. }
  1814. return(DB_SUCCESS);
  1815. }
  1816. /*************************************************************************
  1817. Scans from pointer onwards. Stops if is at the start of a copy of
  1818. 'string' where characters are compared without case sensitivity, and
  1819. only outside `` or "" quotes. Stops also at ''. */
  1820. const char*
  1821. dict_scan_to(
  1822. /*=========*/
  1823. /* out: scanned up to this */
  1824. const char* ptr, /* in: scan from */
  1825. const char* string) /* in: look for this */
  1826. {
  1827. char quote = '';
  1828. for (; *ptr; ptr++) {
  1829. if (*ptr == quote) {
  1830. /* Closing quote character: do not look for
  1831. starting quote or the keyword. */
  1832. quote = '';
  1833. } else if (quote) {
  1834. /* Within quotes: do nothing. */
  1835. } else if (*ptr == '`' || *ptr == '"') {
  1836. /* Starting quote: remember the quote character. */
  1837. quote = *ptr;
  1838. } else {
  1839. /* Outside quotes: look for the keyword. */
  1840. ulint i;
  1841. for (i = 0; string[i]; i++) {
  1842. if (toupper((int)(unsigned char)(ptr[i]))
  1843. != toupper((int)(unsigned char)
  1844. (string[i]))) {
  1845. goto nomatch;
  1846. }
  1847. }
  1848. break;
  1849. nomatch:
  1850. ;
  1851. }
  1852. }
  1853. return(ptr);
  1854. }
  1855. /*************************************************************************
  1856. Accepts a specified string. Comparisons are case-insensitive. */
  1857. const char*
  1858. dict_accept(
  1859. /*========*/
  1860. /* out: if string was accepted, the pointer
  1861. is moved after that, else ptr is returned */
  1862. const char* ptr, /* in: scan from this */
  1863. const char* string, /* in: accept only this string as the next
  1864. non-whitespace string */
  1865. ibool* success)/* out: TRUE if accepted */
  1866. {
  1867. const char* old_ptr = ptr;
  1868. const char* old_ptr2;
  1869. *success = FALSE;
  1870. while (isspace(*ptr)) {
  1871. ptr++;
  1872. }
  1873. old_ptr2 = ptr;
  1874. ptr = dict_scan_to(ptr, string);
  1875. if (*ptr == '' || old_ptr2 != ptr) {
  1876. return(old_ptr);
  1877. }
  1878. *success = TRUE;
  1879. return(ptr + ut_strlen(string));
  1880. }
  1881. /*************************************************************************
  1882. Scans an id. For the lexical definition of an 'id', see the code below.
  1883. Strips backquotes or double quotes from around the id. */
  1884. static
  1885. const char*
  1886. dict_scan_id(
  1887. /*=========*/
  1888. /* out: scanned to */
  1889. const char* ptr, /* in: scanned to */
  1890. mem_heap_t* heap, /* in: heap where to allocate the id
  1891. (NULL=id will not be allocated, but it
  1892. will point to string near ptr) */
  1893. const char** id, /* out,own: the id; NULL if no id was
  1894. scannable */
  1895. ibool accept_also_dot)
  1896. /* in: TRUE if also a dot can appear in a
  1897. non-quoted id; in a quoted id it can appear
  1898. always */
  1899. {
  1900. char quote = '';
  1901. ulint len = 0;
  1902. const char* s;
  1903. char* d;
  1904. ulint id_len;
  1905. byte* b;
  1906. *id = NULL;
  1907. while (isspace(*ptr)) {
  1908. ptr++;
  1909. }
  1910. if (*ptr == '') {
  1911. return(ptr);
  1912. }
  1913. if (*ptr == '`' || *ptr == '"') {
  1914. quote = *ptr++;
  1915. }
  1916. s = ptr;
  1917. if (quote) {
  1918. for (;;) {
  1919. if (!*ptr) {
  1920. /* Syntax error */
  1921. return(ptr);
  1922. }
  1923. if (*ptr == quote) {
  1924. ptr++;
  1925. if (*ptr != quote) {
  1926. break;
  1927. }
  1928. }
  1929. ptr++;
  1930. len++;
  1931. }
  1932. } else {
  1933. while (!isspace(*ptr) && *ptr != '(' && *ptr != ')'
  1934.        && (accept_also_dot || *ptr != '.')
  1935.        && *ptr != ',' && *ptr != '') {
  1936. ptr++;
  1937. }
  1938. len = ptr - s;
  1939. }
  1940. if (quote && heap) {
  1941. *id = d = mem_heap_alloc(heap, len + 1);
  1942. while (len--) {
  1943. if ((*d++ = *s++) == quote) {
  1944. s++;
  1945. }
  1946. }
  1947. *d++ = 0;
  1948. ut_a(*s == quote);
  1949. ut_a(s + 1 == ptr);
  1950. } else if (heap) {
  1951. *id = mem_heap_strdupl(heap, s, len);
  1952. } else {
  1953. /* no heap given: id will point to source string */
  1954. *id = s;
  1955. }
  1956. if (heap && !quote) {
  1957. /* EMS MySQL Manager sometimes adds characters 0xA0 (in
  1958. latin1, a 'non-breakable space') to the end of a table name.
  1959. But isspace(0xA0) is not true, which confuses our foreign key
  1960. parser. After the UTF-8 conversion in ha_innodb.cc, bytes 0xC2
  1961. and 0xA0 are at the end of the string.
  1962. TODO: we should lex the string using thd->charset_info, and
  1963. my_isspace(). Only after that, convert id names to UTF-8. */
  1964. b = (byte*)(*id);
  1965. id_len = strlen(b);
  1966. if (id_len >= 3 && b[id_len - 1] == 0xA0
  1967.        && b[id_len - 2] == 0xC2) {
  1968. /* Strip the 2 last bytes */
  1969. b[id_len - 2] = '';
  1970. }
  1971. }
  1972. return(ptr);
  1973. }
  1974. /*************************************************************************
  1975. Tries to scan a column name. */
  1976. static
  1977. const char*
  1978. dict_scan_col(
  1979. /*==========*/
  1980. /* out: scanned to */
  1981. const char* ptr, /* in: scanned to */
  1982. ibool* success,/* out: TRUE if success */
  1983. dict_table_t* table, /* in: table in which the column is */
  1984. dict_col_t** column, /* out: pointer to column if success */
  1985. mem_heap_t* heap, /* in: heap where to allocate the name */
  1986. const char** name) /* out,own: the column name; NULL if no name
  1987. was scannable */
  1988. {
  1989. dict_col_t* col;
  1990. ulint i;
  1991. *success = FALSE;
  1992. ptr = dict_scan_id(ptr, heap, name, TRUE);
  1993. if (*name == NULL) {
  1994. return(ptr); /* Syntax error */
  1995. }
  1996. if (table == NULL) {
  1997. *success = TRUE;
  1998. *column = NULL;
  1999. } else {
  2000.      for (i = 0; i < dict_table_get_n_cols(table); i++) {
  2001. col = dict_table_get_nth_col(table, i);
  2002. if (0 == innobase_strcasecmp(col->name, *name)) {
  2003.      /* Found */
  2004.      *success = TRUE;
  2005.      *column = col;
  2006.      strcpy((char*) *name, col->name);
  2007.      break;
  2008. }
  2009. }
  2010. }
  2011. return(ptr);
  2012. }
  2013. /*************************************************************************
  2014. Scans a table name from an SQL string. */
  2015. static
  2016. const char*
  2017. dict_scan_table_name(
  2018. /*=================*/
  2019. /* out: scanned to */
  2020. const char* ptr, /* in: scanned to */
  2021. dict_table_t** table, /* out: table object or NULL */
  2022. const char* name, /* in: foreign key table name */
  2023. ibool* success,/* out: TRUE if ok name found */
  2024. mem_heap_t* heap, /* in: heap where to allocate the id */
  2025. const char** ref_name)/* out,own: the table name;
  2026. NULL if no name was scannable */
  2027. {
  2028. const char* database_name = NULL;
  2029. ulint database_name_len = 0;
  2030. const char* table_name = NULL;
  2031. ulint table_name_len;
  2032. const char* scan_name;
  2033. char* ref;
  2034. *success = FALSE;
  2035. *table = NULL;
  2036. ptr = dict_scan_id(ptr, heap, &scan_name, FALSE);
  2037. if (scan_name == NULL) {
  2038. return(ptr); /* Syntax error */
  2039. }
  2040. if (*ptr == '.') {
  2041. /* We scanned the database name; scan also the table name */
  2042. ptr++;
  2043. database_name = scan_name;
  2044. database_name_len = strlen(database_name);
  2045. ptr = dict_scan_id(ptr, heap, &table_name, FALSE);
  2046. if (table_name == NULL) {
  2047. return(ptr); /* Syntax error */
  2048. }
  2049. } else {
  2050. /* To be able to read table dumps made with InnoDB-4.0.17 or
  2051. earlier, we must allow the dot separator between the database
  2052. name and the table name also to appear within a quoted
  2053. identifier! InnoDB used to print a constraint as:
  2054. ... REFERENCES `databasename.tablename` ...
  2055. starting from 4.0.18 it is
  2056. ... REFERENCES `databasename`.`tablename` ... */
  2057. const char* s;
  2058. for (s = scan_name; *s; s++) {
  2059. if (*s == '.') {
  2060. database_name = scan_name;
  2061. database_name_len = s - scan_name;
  2062. scan_name = ++s;
  2063. break;/* to do: multiple dots? */
  2064. }
  2065. }
  2066. table_name = scan_name;
  2067. }
  2068. if (database_name == NULL) {
  2069. /* Use the database name of the foreign key table */
  2070. database_name = name;
  2071. database_name_len = dict_get_db_name_len(name);
  2072. }
  2073. table_name_len = strlen(table_name);
  2074. /* Copy database_name, '/', table_name, '' */
  2075. ref = mem_heap_alloc(heap, database_name_len + table_name_len + 2);
  2076. memcpy(ref, database_name, database_name_len);
  2077. ref[database_name_len] = '/';
  2078. memcpy(ref + database_name_len + 1, table_name, table_name_len + 1);
  2079. #ifndef __WIN__
  2080. if (srv_lower_case_table_names) {
  2081. #endif /* !__WIN__ */
  2082. /* The table name is always put to lower case on Windows. */
  2083. innobase_casedn_str(ref);
  2084. #ifndef __WIN__
  2085. }
  2086. #endif /* !__WIN__ */
  2087. *success = TRUE;
  2088. *ref_name = ref;
  2089. *table = dict_table_get_low(ref);
  2090. return(ptr);
  2091. }
  2092. /*************************************************************************
  2093. Skips one id. The id is allowed to contain also '.'. */
  2094. static
  2095. const char*
  2096. dict_skip_word(
  2097. /*===========*/
  2098. /* out: scanned to */
  2099. const char* ptr, /* in: scanned to */
  2100. ibool* success)/* out: TRUE if success, FALSE if just spaces
  2101. left in string or a syntax error */
  2102. {
  2103. const char* start;
  2104. *success = FALSE;
  2105. ptr = dict_scan_id(ptr, NULL, &start, TRUE);
  2106. if (start) {
  2107. *success = TRUE;
  2108. }
  2109. return(ptr);
  2110. }
  2111. /*************************************************************************
  2112. Removes MySQL comments from an SQL string. A comment is either
  2113. (a) '#' to the end of the line,
  2114. (b) '--<space>' to the end of the line, or
  2115. (c) '<slash><asterisk>' till the next '<asterisk><slash>' (like the familiar
  2116. C comment syntax). */
  2117. static
  2118. char*
  2119. dict_strip_comments(
  2120. /*================*/
  2121. /* out, own: SQL string stripped from
  2122. comments; the caller must free this
  2123. with mem_free()! */
  2124. const char* sql_string) /* in: SQL string */
  2125. {
  2126. char* str;
  2127. const char* sptr;
  2128. char* ptr;
  2129.   /* unclosed quote character (0 if none) */
  2130.   char quote = 0;
  2131. str = mem_alloc(strlen(sql_string) + 1);
  2132. sptr = sql_string;
  2133. ptr = str;
  2134. for (;;) {
  2135. scan_more:
  2136. if (*sptr == '') {
  2137. *ptr = '';
  2138. ut_a(ptr <= str + strlen(sql_string));
  2139. return(str);
  2140. }
  2141. if (*sptr == quote) {
  2142. /* Closing quote character: do not look for
  2143. starting quote or comments. */
  2144. quote = 0;
  2145. } else if (quote) {
  2146. /* Within quotes: do not look for
  2147. starting quotes or comments. */
  2148. } else if (*sptr == '"' || *sptr == '`') {
  2149. /* Starting quote: remember the quote character. */
  2150. quote = *sptr;
  2151. } else if (*sptr == '#'
  2152.                            || (sptr[0] == '-' && sptr[1] == '-' &&
  2153.                                sptr[2] == ' ')) {
  2154. for (;;) {
  2155. /* In Unix a newline is 0x0A while in Windows
  2156. it is 0x0D followed by 0x0A */
  2157. if (*sptr == (char)0x0A
  2158.     || *sptr == (char)0x0D
  2159.     || *sptr == '') {
  2160. goto scan_more;
  2161. }
  2162. sptr++;
  2163. }
  2164. } else if (!quote && *sptr == '/' && *(sptr + 1) == '*') {
  2165. for (;;) {
  2166. if (*sptr == '*' && *(sptr + 1) == '/') {
  2167.       sptr += 2;
  2168. goto scan_more;
  2169. }
  2170. if (*sptr == '') {
  2171. goto scan_more;
  2172. }
  2173. sptr++;
  2174. }
  2175. }
  2176. *ptr = *sptr;
  2177. ptr++;
  2178. sptr++;
  2179. }
  2180. }
  2181. /*************************************************************************
  2182. Finds the highest <number> for foreign key constraints of the table. Looks
  2183. only at the >= 4.0.18-format id's, which are of the form
  2184. databasename/tablename_ibfk_<number>. */
  2185. static
  2186. ulint
  2187. dict_table_get_highest_foreign_id(
  2188. /*==============================*/
  2189. /* out: highest number, 0 if table has no new
  2190. format foreign key constraints */
  2191. dict_table_t* table) /* in: table in the dictionary memory cache */
  2192. {
  2193. dict_foreign_t* foreign;
  2194. char* endp;
  2195. ulint biggest_id = 0;
  2196. ulint id;
  2197. ulint len;
  2198. ut_a(table);
  2199. len = ut_strlen(table->name);
  2200. foreign = UT_LIST_GET_FIRST(table->foreign_list);
  2201. while (foreign) {
  2202. if (ut_strlen(foreign->id) > ((sizeof dict_ibfk) - 1) + len
  2203.     && 0 == ut_memcmp(foreign->id, table->name, len)
  2204.     && 0 == ut_memcmp(foreign->id + len,
  2205. dict_ibfk, (sizeof dict_ibfk) - 1)) {
  2206. /* It is of the >= 4.0.18 format */
  2207. id = strtoul(foreign->id + len + ((sizeof dict_ibfk) - 1),
  2208. &endp, 10);
  2209. if (*endp == '') {
  2210. ut_a(id != biggest_id);
  2211. if (id > biggest_id) {
  2212. biggest_id = id;
  2213. }
  2214. }
  2215. }
  2216. foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
  2217. }
  2218. return(biggest_id);
  2219. }
  2220. /*************************************************************************
  2221. Reports a simple foreign key create clause syntax error. */
  2222. static
  2223. void
  2224. dict_foreign_report_syntax_err(
  2225. /*===========================*/
  2226. const char* name, /* in: table name */
  2227. const char* start_of_latest_foreign,
  2228. /* in: start of the foreign key clause
  2229. in the SQL string */
  2230. const char* ptr) /* in: place of the syntax error */
  2231. {
  2232. FILE*  ef = dict_foreign_err_file;
  2233. mutex_enter(&dict_foreign_err_mutex);
  2234. dict_foreign_error_report_low(ef, name);
  2235. fprintf(ef, "%s:nSyntax error close to:n%sn",
  2236. start_of_latest_foreign, ptr);
  2237. mutex_exit(&dict_foreign_err_mutex);
  2238. }
  2239. /*************************************************************************
  2240. Scans a table create SQL string and adds to the data dictionary the foreign
  2241. key constraints declared in the string. This function should be called after
  2242. the indexes for a table have been created. Each foreign key constraint must
  2243. be accompanied with indexes in both participating tables. The indexes are
  2244. allowed to contain more fields than mentioned in the constraint. */
  2245. static
  2246. ulint
  2247. dict_create_foreign_constraints_low(
  2248. /*================================*/
  2249. /* out: error code or DB_SUCCESS */
  2250. trx_t* trx, /* in: transaction */
  2251. mem_heap_t* heap, /* in: memory heap */
  2252. const char* sql_string,
  2253. /* in: CREATE TABLE or ALTER TABLE statement
  2254. where foreign keys are declared like:
  2255. FOREIGN KEY (a, b) REFERENCES table2(c, d),
  2256. table2 can be written also with the database
  2257. name before it: test.table2; the default
  2258. database is the database of parameter name */
  2259. const char* name) /* in: table full name in the normalized form
  2260. database_name/table_name */
  2261. {
  2262. dict_table_t* table;
  2263. dict_table_t* referenced_table;
  2264. dict_table_t* table_to_alter;
  2265. ulint highest_id_so_far = 0;
  2266. dict_index_t* index;
  2267. dict_foreign_t* foreign;
  2268.   const char* ptr = sql_string;
  2269. const char* start_of_latest_foreign = sql_string;
  2270. FILE* ef = dict_foreign_err_file;
  2271. const char* constraint_name;
  2272. ibool success;
  2273. ulint error;
  2274. const char* ptr1;
  2275. const char* ptr2;
  2276. ulint i;
  2277. ulint j;
  2278. ibool is_on_delete;
  2279. ulint n_on_deletes;
  2280. ulint n_on_updates;
  2281. dict_col_t* columns[500];
  2282. const char* column_names[500];
  2283. const char* referenced_table_name;
  2284. #ifdef UNIV_SYNC_DEBUG
  2285. ut_ad(mutex_own(&(dict_sys->mutex)));
  2286. #endif /* UNIV_SYNC_DEBUG */
  2287. table = dict_table_get_low(name);
  2288. if (table == NULL) {
  2289. mutex_enter(&dict_foreign_err_mutex);
  2290. dict_foreign_error_report_low(ef, name);
  2291. fprintf(ef,
  2292. "Cannot find the table in the internal data dictionary of InnoDB.n"
  2293. "Create table statement:n%sn", sql_string);
  2294. mutex_exit(&dict_foreign_err_mutex);
  2295. return(DB_ERROR);
  2296. }
  2297. /* First check if we are actually doing an ALTER TABLE, and in that
  2298. case look for the table being altered */
  2299. ptr = dict_accept(ptr, "ALTER", &success);
  2300. if (!success) {
  2301. goto loop;
  2302. }
  2303. ptr = dict_accept(ptr, "TABLE", &success);
  2304. if (!success) {
  2305. goto loop;
  2306. }
  2307. /* We are doing an ALTER TABLE: scan the table name we are altering */
  2308. ptr = dict_scan_table_name(ptr, &table_to_alter, name,
  2309. &success, heap, &referenced_table_name);
  2310. if (!success) {
  2311. fprintf(stderr,
  2312. "InnoDB: Error: could not find the table being ALTERED in:n%sn", sql_string);
  2313. return(DB_ERROR);
  2314. }
  2315. /* Starting from 4.0.18 and 4.1.2, we generate foreign key id's in the
  2316. format databasename/tablename_ibfk_<number>, where <number> is local
  2317. to the table; look for the highest <number> for table_to_alter, so
  2318. that we can assign to new constraints higher numbers. */
  2319. /* If we are altering a temporary table, the table name after ALTER
  2320. TABLE does not correspond to the internal table name, and
  2321. table_to_alter is NULL. TODO: should we fix this somehow? */
  2322. if (table_to_alter == NULL) {
  2323. highest_id_so_far = 0;
  2324. } else {
  2325. highest_id_so_far = dict_table_get_highest_foreign_id(
  2326. table_to_alter);
  2327. }
  2328. /* Scan for foreign key declarations in a loop */
  2329. loop:
  2330. /* Scan either to "CONSTRAINT" or "FOREIGN", whichever is closer */
  2331. ptr1 = dict_scan_to(ptr, "CONSTRAINT");
  2332. ptr2 = dict_scan_to(ptr, "FOREIGN");
  2333. constraint_name = NULL;
  2334. if (ptr1 < ptr2) {
  2335. /* The user may have specified a constraint name. Pick it so
  2336. that we can store 'databasename/constraintname' as the id of
  2337. of the constraint to system tables. */
  2338. ptr = ptr1;
  2339. ptr = dict_accept(ptr, "CONSTRAINT", &success);
  2340. ut_a(success);
  2341. if (!isspace(*ptr) && *ptr != '"' && *ptr != '`') {
  2342.          goto loop;
  2343. }
  2344. while (isspace(*ptr)) {
  2345. ptr++;
  2346. }
  2347. /* read constraint name unless got "CONSTRAINT FOREIGN" */
  2348. if (ptr != ptr2) {
  2349. ptr = dict_scan_id(ptr, heap, &constraint_name, FALSE);
  2350. }
  2351. } else {
  2352. ptr = ptr2;
  2353. }
  2354. if (*ptr == '') {
  2355. /**********************************************************/
  2356. /* The following call adds the foreign key constraints
  2357. to the data dictionary system tables on disk */
  2358. error = dict_create_add_foreigns_to_dictionary(
  2359. highest_id_so_far, table, trx);
  2360. return(error);
  2361. }
  2362. start_of_latest_foreign = ptr;
  2363. ptr = dict_accept(ptr, "FOREIGN", &success);
  2364. if (!success) {
  2365. goto loop;
  2366. }
  2367. if (!isspace(*ptr)) {
  2368.         goto loop;
  2369. }
  2370. ptr = dict_accept(ptr, "KEY", &success);
  2371. if (!success) {
  2372. goto loop;
  2373. }
  2374. ptr = dict_accept(ptr, "(", &success);
  2375. if (!success) {
  2376. /* MySQL allows also an index id before the '('; we
  2377. skip it */
  2378. ptr = dict_skip_word(ptr, &success);
  2379. if (!success) {
  2380. dict_foreign_report_syntax_err(name,
  2381. start_of_latest_foreign, ptr);
  2382. return(DB_CANNOT_ADD_CONSTRAINT);
  2383. }
  2384. ptr = dict_accept(ptr, "(", &success);
  2385. if (!success) {
  2386. /* We do not flag a syntax error here because in an
  2387. ALTER TABLE we may also have DROP FOREIGN KEY abc */
  2388.         goto loop;
  2389. }
  2390. }
  2391. i = 0;
  2392. /* Scan the columns in the first list */
  2393. col_loop1:
  2394. ut_a(i < (sizeof column_names) / sizeof *column_names);
  2395. ptr = dict_scan_col(ptr, &success, table, columns + i,
  2396. heap, column_names + i);
  2397. if (!success) {
  2398. mutex_enter(&dict_foreign_err_mutex);
  2399. dict_foreign_error_report_low(ef, name);
  2400. fprintf(ef, "%s:nCannot resolve column name close to:n%sn",
  2401. start_of_latest_foreign, ptr);
  2402. mutex_exit(&dict_foreign_err_mutex);
  2403. return(DB_CANNOT_ADD_CONSTRAINT);
  2404. }
  2405. i++;
  2406. ptr = dict_accept(ptr, ",", &success);
  2407. if (success) {
  2408. goto col_loop1;
  2409. }
  2410. ptr = dict_accept(ptr, ")", &success);
  2411. if (!success) {
  2412. dict_foreign_report_syntax_err(name, start_of_latest_foreign,
  2413. ptr);
  2414. return(DB_CANNOT_ADD_CONSTRAINT);
  2415. }
  2416. /* Try to find an index which contains the columns
  2417. as the first fields and in the right order */
  2418. index = dict_foreign_find_index(table, column_names, i, NULL);
  2419. if (!index) {
  2420. mutex_enter(&dict_foreign_err_mutex);
  2421. dict_foreign_error_report_low(ef, name);
  2422. fputs("There is no index in table ", ef);
  2423. ut_print_name(ef, NULL, name);
  2424. fprintf(ef, " where the columns appearn"
  2425. "as the first columns. Constraint:n%sn"
  2426. "See http://dev.mysql.com/doc/mysql/en/InnoDB_foreign_key_constraints.htmln"
  2427. "for correct foreign key definition.n",
  2428. start_of_latest_foreign);
  2429. mutex_exit(&dict_foreign_err_mutex);
  2430. return(DB_CANNOT_ADD_CONSTRAINT);
  2431. }
  2432. ptr = dict_accept(ptr, "REFERENCES", &success);
  2433. if (!success || !isspace(*ptr)) {
  2434. dict_foreign_report_syntax_err(name, start_of_latest_foreign,
  2435. ptr);
  2436. return(DB_CANNOT_ADD_CONSTRAINT);
  2437. }
  2438. /* Let us create a constraint struct */
  2439. foreign = dict_mem_foreign_create();
  2440. if (constraint_name) {
  2441. ulint db_len;
  2442. /* Catenate 'databasename/' to the constraint name specified
  2443. by the user: we conceive the constraint as belonging to the
  2444. same MySQL 'database' as the table itself. We store the name
  2445. to foreign->id. */
  2446. db_len = dict_get_db_name_len(table->name);
  2447. foreign->id = mem_heap_alloc(foreign->heap,
  2448. db_len + strlen(constraint_name) + 2);
  2449. ut_memcpy(foreign->id, table->name, db_len);
  2450. foreign->id[db_len] = '/';
  2451. strcpy(foreign->id + db_len + 1, constraint_name);
  2452. }
  2453. foreign->foreign_table = table;
  2454. foreign->foreign_table_name = mem_heap_strdup(foreign->heap,
  2455. table->name);
  2456. foreign->foreign_index = index;
  2457. foreign->n_fields = i;
  2458. foreign->foreign_col_names = mem_heap_alloc(foreign->heap,
  2459. i * sizeof(void*));
  2460. for (i = 0; i < foreign->n_fields; i++) {
  2461. foreign->foreign_col_names[i] =
  2462. mem_heap_strdup(foreign->heap, columns[i]->name);
  2463. }
  2464. ptr = dict_scan_table_name(ptr, &referenced_table, name,
  2465. &success, heap, &referenced_table_name);
  2466. /* Note that referenced_table can be NULL if the user has suppressed
  2467. checking of foreign key constraints! */
  2468. if (!success || (!referenced_table && trx->check_foreigns)) {
  2469. dict_foreign_free(foreign);
  2470. mutex_enter(&dict_foreign_err_mutex);
  2471. dict_foreign_error_report_low(ef, name);
  2472. fprintf(ef, "%s:nCannot resolve table name close to:n"
  2473. "%sn",
  2474. start_of_latest_foreign, ptr);
  2475. mutex_exit(&dict_foreign_err_mutex);
  2476. return(DB_CANNOT_ADD_CONSTRAINT);
  2477. }
  2478. ptr = dict_accept(ptr, "(", &success);
  2479. if (!success) {
  2480. dict_foreign_free(foreign);
  2481. dict_foreign_report_syntax_err(name, start_of_latest_foreign,
  2482. ptr);
  2483. return(DB_CANNOT_ADD_CONSTRAINT);
  2484. }
  2485. /* Scan the columns in the second list */
  2486. i = 0;
  2487. col_loop2:
  2488. ptr = dict_scan_col(ptr, &success, referenced_table, columns + i,
  2489. heap, column_names + i);
  2490. i++;
  2491. if (!success) {
  2492. dict_foreign_free(foreign);
  2493. mutex_enter(&dict_foreign_err_mutex);
  2494. dict_foreign_error_report_low(ef, name);
  2495. fprintf(ef, "%s:nCannot resolve column name close to:n"
  2496. "%sn",
  2497. start_of_latest_foreign, ptr);
  2498. mutex_exit(&dict_foreign_err_mutex);
  2499. return(DB_CANNOT_ADD_CONSTRAINT);
  2500. }
  2501. ptr = dict_accept(ptr, ",", &success);
  2502. if (success) {
  2503. goto col_loop2;
  2504. }
  2505. ptr = dict_accept(ptr, ")", &success);
  2506. if (!success || foreign->n_fields != i) {
  2507. dict_foreign_free(foreign);
  2508. dict_foreign_report_syntax_err(name, start_of_latest_foreign,
  2509. ptr);
  2510. return(DB_CANNOT_ADD_CONSTRAINT);
  2511. }
  2512. n_on_deletes = 0;
  2513. n_on_updates = 0;
  2514. scan_on_conditions:
  2515. /* Loop here as long as we can find ON ... conditions */
  2516. ptr = dict_accept(ptr, "ON", &success);
  2517. if (!success) {
  2518. goto try_find_index;
  2519. }
  2520. ptr = dict_accept(ptr, "DELETE", &success);
  2521. if (!success) {
  2522. ptr = dict_accept(ptr, "UPDATE", &success);
  2523. if (!success) {
  2524. dict_foreign_free(foreign);
  2525. dict_foreign_report_syntax_err(name,
  2526. start_of_latest_foreign, ptr);
  2527. return(DB_CANNOT_ADD_CONSTRAINT);
  2528. }
  2529. is_on_delete = FALSE;
  2530. n_on_updates++;
  2531. } else {
  2532. is_on_delete = TRUE;
  2533. n_on_deletes++;
  2534. }
  2535. ptr = dict_accept(ptr, "RESTRICT", &success);
  2536. if (success) {
  2537. goto scan_on_conditions;
  2538. }
  2539. ptr = dict_accept(ptr, "CASCADE", &success);
  2540. if (success) {
  2541. if (is_on_delete) {
  2542. foreign->type |= DICT_FOREIGN_ON_DELETE_CASCADE;
  2543. } else {
  2544. foreign->type |= DICT_FOREIGN_ON_UPDATE_CASCADE;
  2545. }
  2546. goto scan_on_conditions;
  2547. }
  2548. ptr = dict_accept(ptr, "NO", &success);
  2549. if (success) {
  2550. ptr = dict_accept(ptr, "ACTION", &success);
  2551. if (!success) {
  2552. dict_foreign_free(foreign);
  2553. dict_foreign_report_syntax_err(name,
  2554. start_of_latest_foreign, ptr);
  2555. return(DB_CANNOT_ADD_CONSTRAINT);
  2556. }
  2557. if (is_on_delete) {
  2558. foreign->type |= DICT_FOREIGN_ON_DELETE_NO_ACTION;
  2559. } else {
  2560. foreign->type |= DICT_FOREIGN_ON_UPDATE_NO_ACTION;
  2561. }
  2562. goto scan_on_conditions;
  2563. }
  2564. ptr = dict_accept(ptr, "SET", &success);
  2565. if (!success) {
  2566. dict_foreign_free(foreign);
  2567. dict_foreign_report_syntax_err(name, start_of_latest_foreign,
  2568. ptr);
  2569. return(DB_CANNOT_ADD_CONSTRAINT);
  2570. }
  2571. ptr = dict_accept(ptr, "NULL", &success);
  2572. if (!success) {
  2573. dict_foreign_free(foreign);
  2574. dict_foreign_report_syntax_err(name, start_of_latest_foreign,
  2575. ptr);
  2576. return(DB_CANNOT_ADD_CONSTRAINT);
  2577. }
  2578. for (j = 0; j < foreign->n_fields; j++) {
  2579. if ((dict_index_get_nth_type(
  2580. foreign->foreign_index, j)->prtype)
  2581. & DATA_NOT_NULL) {
  2582. /* It is not sensible to define SET NULL
  2583. if the column is not allowed to be NULL! */
  2584. dict_foreign_free(foreign);
  2585. mutex_enter(&dict_foreign_err_mutex);
  2586. dict_foreign_error_report_low(ef, name);
  2587. fprintf(ef, "%s:n"
  2588. "You have defined a SET NULL condition though some of then"
  2589. "columns are defined as NOT NULL.n", start_of_latest_foreign);
  2590. mutex_exit(&dict_foreign_err_mutex);
  2591. return(DB_CANNOT_ADD_CONSTRAINT);
  2592. }
  2593. }
  2594. if (is_on_delete) {
  2595. foreign->type |= DICT_FOREIGN_ON_DELETE_SET_NULL;
  2596. } else {
  2597. foreign->type |= DICT_FOREIGN_ON_UPDATE_SET_NULL;
  2598. }
  2599. goto scan_on_conditions;
  2600. try_find_index:
  2601. if (n_on_deletes > 1 || n_on_updates > 1) {
  2602. /* It is an error to define more than 1 action */
  2603. dict_foreign_free(foreign);
  2604. mutex_enter(&dict_foreign_err_mutex);
  2605. dict_foreign_error_report_low(ef, name);
  2606. fprintf(ef, "%s:n"
  2607. "You have twice an ON DELETE clause or twice an ON UPDATE clause.n",
  2608. start_of_latest_foreign);
  2609. mutex_exit(&dict_foreign_err_mutex);
  2610. return(DB_CANNOT_ADD_CONSTRAINT);
  2611. }
  2612. /* Try to find an index which contains the columns as the first fields
  2613. and in the right order, and the types are the same as in
  2614. foreign->foreign_index */
  2615. if (referenced_table) {
  2616. index = dict_foreign_find_index(referenced_table,
  2617. column_names, i,
  2618. foreign->foreign_index);
  2619. if (!index) {
  2620. dict_foreign_free(foreign);
  2621. mutex_enter(&dict_foreign_err_mutex);
  2622. dict_foreign_error_report_low(ef, name);
  2623. fprintf(ef, "%s:n"
  2624. "Cannot find an index in the referenced table where then"
  2625. "referenced columns appear as the first columns, or column typesn"
  2626. "in the table and the referenced table do not match for constraint.n"
  2627. "Note that the internal storage type of ENUM and SET changed inn"
  2628. "tables created with >= InnoDB-4.1.12, and such columns in old tablesn"
  2629. "cannot be referenced by such columns in new tables.n"
  2630. "See http://dev.mysql.com/doc/mysql/en/InnoDB_foreign_key_constraints.htmln"
  2631. "for correct foreign key definition.n",
  2632. start_of_latest_foreign);
  2633. mutex_exit(&dict_foreign_err_mutex);
  2634. return(DB_CANNOT_ADD_CONSTRAINT);
  2635. }
  2636. } else {
  2637. ut_a(trx->check_foreigns == FALSE);
  2638. index = NULL;
  2639. }
  2640. foreign->referenced_index = index;
  2641. foreign->referenced_table = referenced_table;
  2642. foreign->referenced_table_name = mem_heap_strdup(foreign->heap,
  2643. referenced_table_name);
  2644. foreign->referenced_col_names = mem_heap_alloc(foreign->heap,
  2645. i * sizeof(void*));
  2646. for (i = 0; i < foreign->n_fields; i++) {
  2647. foreign->referenced_col_names[i]
  2648. = mem_heap_strdup(foreign->heap, column_names[i]);
  2649. }
  2650. /* We found an ok constraint definition: add to the lists */
  2651. UT_LIST_ADD_LAST(foreign_list, table->foreign_list, foreign);
  2652. if (referenced_table) {
  2653. UT_LIST_ADD_LAST(referenced_list,
  2654. referenced_table->referenced_list,
  2655. foreign);
  2656. }
  2657. goto loop;
  2658. }
  2659. /*************************************************************************
  2660. Scans a table create SQL string and adds to the data dictionary the foreign
  2661. key constraints declared in the string. This function should be called after
  2662. the indexes for a table have been created. Each foreign key constraint must
  2663. be accompanied with indexes in both participating tables. The indexes are
  2664. allowed to contain more fields than mentioned in the constraint. */
  2665. ulint
  2666. dict_create_foreign_constraints(
  2667. /*============================*/
  2668. /* out: error code or DB_SUCCESS */
  2669. trx_t* trx, /* in: transaction */
  2670. const char* sql_string, /* in: table create statement where
  2671. foreign keys are declared like:
  2672. FOREIGN KEY (a, b) REFERENCES
  2673. table2(c, d), table2 can be written
  2674. also with the database
  2675. name before it: test.table2; the
  2676. default database id the database of
  2677. parameter name */
  2678. const char* name) /* in: table full name in the
  2679. normalized form
  2680. database_name/table_name */
  2681. {
  2682. char* str;
  2683. ulint err;
  2684. mem_heap_t* heap;
  2685. str = dict_strip_comments(sql_string);
  2686. heap = mem_heap_create(10000);
  2687. err = dict_create_foreign_constraints_low(trx, heap, str, name);
  2688. mem_heap_free(heap);
  2689. mem_free(str);
  2690. return(err);
  2691. }
  2692. /**************************************************************************
  2693. Parses the CONSTRAINT id's to be dropped in an ALTER TABLE statement. */
  2694. ulint
  2695. dict_foreign_parse_drop_constraints(
  2696. /*================================*/
  2697. /* out: DB_SUCCESS or
  2698. DB_CANNOT_DROP_CONSTRAINT if
  2699. syntax error or the constraint
  2700. id does not match */
  2701. mem_heap_t* heap, /* in: heap from which we can
  2702. allocate memory */
  2703. trx_t* trx, /* in: transaction */
  2704. dict_table_t* table, /* in: table */
  2705. ulint* n, /* out: number of constraints
  2706. to drop */
  2707. const char*** constraints_to_drop) /* out: id's of the
  2708. constraints to drop */
  2709. {
  2710. dict_foreign_t* foreign;
  2711. ibool success;
  2712. char* str;
  2713. const char* ptr;
  2714. const char* id;
  2715. FILE* ef = dict_foreign_err_file;
  2716. *n = 0;
  2717. *constraints_to_drop = mem_heap_alloc(heap, 1000 * sizeof(char*));
  2718. str = dict_strip_comments(*(trx->mysql_query_str));
  2719. ptr = str;
  2720. #ifdef UNIV_SYNC_DEBUG
  2721. ut_ad(mutex_own(&(dict_sys->mutex)));
  2722. #endif /* UNIV_SYNC_DEBUG */
  2723. loop:
  2724. ptr = dict_scan_to(ptr, "DROP");
  2725. if (*ptr == '') {
  2726. mem_free(str);
  2727. return(DB_SUCCESS);
  2728. }
  2729. ptr = dict_accept(ptr, "DROP", &success);
  2730. if (!isspace(*ptr)) {
  2731.         goto loop;
  2732. }
  2733. ptr = dict_accept(ptr, "FOREIGN", &success);
  2734. if (!success) {
  2735.         goto loop;
  2736. }
  2737. ptr = dict_accept(ptr, "KEY", &success);
  2738. if (!success) {
  2739. goto syntax_error;
  2740. }
  2741. ptr = dict_scan_id(ptr, heap, &id, TRUE);
  2742. if (id == NULL) {
  2743. goto syntax_error;
  2744. }
  2745. ut_a(*n < 1000);
  2746. (*constraints_to_drop)[*n] = id;
  2747. (*n)++;
  2748. /* Look for the given constraint id */
  2749. foreign = UT_LIST_GET_FIRST(table->foreign_list);
  2750. while (foreign != NULL) {
  2751. if (0 == strcmp(foreign->id, id)
  2752.     || (strchr(foreign->id, '/')
  2753. && 0 == strcmp(id,
  2754. dict_remove_db_name(foreign->id)))) {
  2755. /* Found */
  2756. break;
  2757. }
  2758. foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
  2759. }
  2760. if (foreign == NULL) {
  2761. mutex_enter(&dict_foreign_err_mutex);
  2762. rewind(ef);
  2763. ut_print_timestamp(ef);
  2764. fputs(
  2765. " Error in dropping of a foreign key constraint of table ", ef);
  2766. ut_print_name(ef, NULL, table->name);
  2767. fputs(",n"
  2768. "in SQL commandn", ef);
  2769. fputs(str, ef);
  2770. fputs("nCannot find a constraint with the given id ", ef);
  2771. ut_print_name(ef, NULL, id);
  2772. fputs(".n", ef);
  2773. mutex_exit(&dict_foreign_err_mutex);
  2774. mem_free(str);
  2775. return(DB_CANNOT_DROP_CONSTRAINT);
  2776. }
  2777. goto loop;
  2778. syntax_error:
  2779. mutex_enter(&dict_foreign_err_mutex);
  2780. rewind(ef);
  2781. ut_print_timestamp(ef);
  2782. fputs(
  2783. " Syntax error in dropping of a foreign key constraint of table ", ef);
  2784. ut_print_name(ef, NULL, table->name);
  2785. fprintf(ef, ",n"
  2786. "close to:n%sn in SQL commandn%sn", ptr, str);
  2787. mutex_exit(&dict_foreign_err_mutex);
  2788. mem_free(str);
  2789. return(DB_CANNOT_DROP_CONSTRAINT);
  2790. }
  2791. /*==================== END OF FOREIGN KEY PROCESSING ====================*/
  2792. /**************************************************************************
  2793. Returns an index object if it is found in the dictionary cache. */
  2794. dict_index_t*
  2795. dict_index_get_if_in_cache(
  2796. /*=======================*/
  2797. /* out: index, NULL if not found */
  2798. dulint index_id) /* in: index id */
  2799. {
  2800. dict_table_t* table;
  2801. dict_index_t* index;
  2802. if (dict_sys == NULL) {
  2803. return(NULL);
  2804. }
  2805. mutex_enter(&(dict_sys->mutex));
  2806. table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
  2807. while (table) {
  2808. index = UT_LIST_GET_FIRST(table->indexes);
  2809. while (index) {
  2810. if (0 == ut_dulint_cmp(index->id, index_id)) {
  2811. goto found;
  2812. }
  2813. index = UT_LIST_GET_NEXT(indexes, index);
  2814. }
  2815. table = UT_LIST_GET_NEXT(table_LRU, table);
  2816. }
  2817. index = NULL;
  2818. found:
  2819. mutex_exit(&(dict_sys->mutex));
  2820. return(index);
  2821. }
  2822. /**************************************************************************
  2823. Creates an index tree struct. */
  2824. dict_tree_t*
  2825. dict_tree_create(
  2826. /*=============*/
  2827. /* out, own: created tree */
  2828. dict_index_t* index) /* in: the index for which to create: in the
  2829. case of a mixed tree, this should be the
  2830. index of the cluster object */
  2831. {
  2832. dict_tree_t* tree;
  2833. tree = mem_alloc(sizeof(dict_tree_t));
  2834. /* Inherit info from the index */
  2835. tree->type = index->type;
  2836. tree->space = index->space;
  2837. tree->page = index->page_no;
  2838. tree->id = index->id;
  2839. UT_LIST_INIT(tree->tree_indexes);
  2840. tree->magic_n = DICT_TREE_MAGIC_N;
  2841. rw_lock_create(&(tree->lock));
  2842. rw_lock_set_level(&(tree->lock), SYNC_INDEX_TREE);
  2843. return(tree);
  2844. }
  2845. /**************************************************************************
  2846. Frees an index tree struct. */
  2847. void
  2848. dict_tree_free(
  2849. /*===========*/
  2850. dict_tree_t* tree) /* in, own: index tree */
  2851. {
  2852. ut_a(tree);
  2853. ut_ad(tree->magic_n == DICT_TREE_MAGIC_N);
  2854. rw_lock_free(&(tree->lock));
  2855. mem_free(tree);
  2856. }
  2857. /**************************************************************************
  2858. In an index tree, finds the index corresponding to a record in the tree. */
  2859. UNIV_INLINE
  2860. dict_index_t*
  2861. dict_tree_find_index_low(
  2862. /*=====================*/
  2863. /* out: index */
  2864. dict_tree_t* tree, /* in: index tree */
  2865. rec_t* rec) /* in: record for which to find correct
  2866. index */
  2867. {
  2868. dict_index_t* index;
  2869. dict_table_t* table;
  2870. dulint mix_id;
  2871. ulint len;
  2872. index = UT_LIST_GET_FIRST(tree->tree_indexes);
  2873. ut_ad(index);
  2874. table = index->table;
  2875. if ((index->type & DICT_CLUSTERED)
  2876. && (table->type != DICT_TABLE_ORDINARY)) {
  2877. /* Get the mix id of the record */
  2878. mix_id = mach_dulint_read_compressed(
  2879. rec_get_nth_field(rec, table->mix_len, &len));
  2880. while (ut_dulint_cmp(table->mix_id, mix_id) != 0) {
  2881. index = UT_LIST_GET_NEXT(tree_indexes, index);
  2882. table = index->table;
  2883. ut_ad(index);
  2884. }
  2885. }
  2886. return(index);
  2887. }
  2888. /**************************************************************************
  2889. In an index tree, finds the index corresponding to a record in the tree. */
  2890. dict_index_t*
  2891. dict_tree_find_index(
  2892. /*=================*/
  2893. /* out: index */
  2894. dict_tree_t* tree, /* in: index tree */
  2895. rec_t* rec) /* in: record for which to find correct
  2896. index */
  2897. {
  2898. dict_index_t* index;
  2899. index = dict_tree_find_index_low(tree, rec);
  2900. return(index);
  2901. }
  2902. /**************************************************************************
  2903. In an index tree, finds the index corresponding to a dtuple which is used
  2904. in a search to a tree. */
  2905. dict_index_t*
  2906. dict_tree_find_index_for_tuple(
  2907. /*===========================*/
  2908. /* out: index; NULL if the tuple does not
  2909. contain the mix id field in a mixed tree */
  2910. dict_tree_t* tree, /* in: index tree */
  2911. dtuple_t* tuple) /* in: tuple for which to find index */
  2912. {
  2913. dict_index_t* index;
  2914. dict_table_t* table;
  2915. dulint mix_id;
  2916. ut_ad(dtuple_check_typed(tuple));
  2917. if (UT_LIST_GET_LEN(tree->tree_indexes) == 1) {
  2918. return(UT_LIST_GET_FIRST(tree->tree_indexes));
  2919. }
  2920. index = UT_LIST_GET_FIRST(tree->tree_indexes);
  2921. ut_ad(index);
  2922. table = index->table;
  2923. if (dtuple_get_n_fields(tuple) <= table->mix_len) {
  2924. return(NULL);
  2925. }
  2926. /* Get the mix id of the record */
  2927. mix_id = mach_dulint_read_compressed(
  2928. dfield_get_data(
  2929. dtuple_get_nth_field(tuple, table->mix_len)));
  2930. while (ut_dulint_cmp(table->mix_id, mix_id) != 0) {
  2931. index = UT_LIST_GET_NEXT(tree_indexes, index);
  2932. table = index->table;
  2933. ut_ad(index);
  2934. }
  2935. return(index);
  2936. }
  2937. /**************************************************************************
  2938. Checks that a tuple has n_fields_cmp value in a sensible range, so that
  2939. no comparison can occur with the page number field in a node pointer. */
  2940. ibool
  2941. dict_tree_check_search_tuple(
  2942. /*=========================*/
  2943. /* out: TRUE if ok */
  2944. dict_tree_t* tree, /* in: index tree */
  2945. dtuple_t* tuple) /* in: tuple used in a search */
  2946. {
  2947. dict_index_t* index;
  2948. index = dict_tree_find_index_for_tuple(tree, tuple);
  2949. if (index == NULL) {
  2950. return(TRUE);
  2951. }
  2952. ut_a(dtuple_get_n_fields_cmp(tuple)
  2953. <= dict_index_get_n_unique_in_tree(index));
  2954. return(TRUE);
  2955. }
  2956. /**************************************************************************
  2957. Builds a node pointer out of a physical record and a page number. */
  2958. dtuple_t*
  2959. dict_tree_build_node_ptr(
  2960. /*=====================*/
  2961. /* out, own: node pointer */
  2962. dict_tree_t* tree, /* in: index tree */
  2963. rec_t* rec, /* in: record for which to build node
  2964. pointer */
  2965. ulint page_no,/* in: page number to put in node pointer */
  2966. mem_heap_t* heap, /* in: memory heap where pointer created */
  2967. ulint           level)  /* in: level of rec in tree: 0 means leaf
  2968. level */
  2969. {
  2970. dtuple_t* tuple;
  2971. dict_index_t* ind;
  2972. dfield_t* field;
  2973. byte* buf;
  2974. ulint n_unique;
  2975. ind = dict_tree_find_index_low(tree, rec);
  2976. if (tree->type & DICT_UNIVERSAL) {
  2977. /* In a universal index tree, we take the whole record as
  2978. the node pointer if the reord is on the leaf level,
  2979. on non-leaf levels we remove the last field, which
  2980. contains the page number of the child page */
  2981. n_unique = rec_get_n_fields(rec);
  2982. if (level > 0) {
  2983.         ut_a(n_unique > 1);
  2984.         n_unique--;
  2985. }
  2986. } else {
  2987. n_unique = dict_index_get_n_unique_in_tree(ind);
  2988. }
  2989. tuple = dtuple_create(heap, n_unique + 1);
  2990. /* When searching in the tree for the node pointer, we must not do
  2991. comparison on the last field, the page number field, as on upper
  2992. levels in the tree there may be identical node pointers with a
  2993. different page number; therefore, we set the n_fields_cmp to one
  2994. less: */
  2995. dtuple_set_n_fields_cmp(tuple, n_unique);
  2996. dict_index_copy_types(tuple, ind, n_unique);
  2997. buf = mem_heap_alloc(heap, 4);
  2998. mach_write_to_4(buf, page_no);
  2999. field = dtuple_get_nth_field(tuple, n_unique);
  3000. dfield_set_data(field, buf, 4);
  3001. dtype_set(dfield_get_type(field), DATA_SYS_CHILD, 0, 0, 0);
  3002. rec_copy_prefix_to_dtuple(tuple, rec, n_unique, heap);
  3003. ut_ad(dtuple_check_typed(tuple));
  3004. return(tuple);
  3005. }
  3006. /**************************************************************************
  3007. Copies an initial segment of a physical record, long enough to specify an
  3008. index entry uniquely. */
  3009. rec_t*
  3010. dict_tree_copy_rec_order_prefix(
  3011. /*============================*/
  3012. /* out: pointer to the prefix record */
  3013. dict_tree_t* tree, /* in: index tree */
  3014. rec_t* rec, /* in: record for which to copy prefix */
  3015. byte** buf, /* in/out: memory buffer for the copied prefix,
  3016. or NULL */
  3017. ulint* buf_size)/* in/out: buffer size */
  3018. {
  3019. dict_index_t* ind;
  3020. rec_t* order_rec;
  3021. ulint n_fields;
  3022. ind = dict_tree_find_index_low(tree, rec);
  3023. n_fields = dict_index_get_n_unique_in_tree(ind);
  3024. if (tree->type & DICT_UNIVERSAL) {
  3025. n_fields = rec_get_n_fields(rec);
  3026. }
  3027. order_rec = rec_copy_prefix_to_buf(rec, n_fields, buf, buf_size);
  3028. return(order_rec);
  3029. }
  3030. /**************************************************************************
  3031. Builds a typed data tuple out of a physical record. */
  3032. dtuple_t*
  3033. dict_tree_build_data_tuple(
  3034. /*=======================*/
  3035. /* out, own: data tuple */
  3036. dict_tree_t* tree, /* in: index tree */
  3037. rec_t* rec, /* in: record for which to build data tuple */
  3038. mem_heap_t* heap) /* in: memory heap where tuple created */
  3039. {
  3040. dtuple_t* tuple;
  3041. dict_index_t* ind;
  3042. ulint n_fields;
  3043. ind = dict_tree_find_index_low(tree, rec);
  3044. n_fields = rec_get_n_fields(rec);
  3045. tuple = dtuple_create(heap, n_fields); 
  3046. dict_index_copy_types(tuple, ind, n_fields);
  3047. rec_copy_prefix_to_dtuple(tuple, rec, n_fields, heap);
  3048. ut_ad(dtuple_check_typed(tuple));
  3049. return(tuple);
  3050. }
  3051. /*************************************************************************
  3052. Calculates the minimum record length in an index. */
  3053. ulint
  3054. dict_index_calc_min_rec_len(
  3055. /*========================*/
  3056. dict_index_t* index) /* in: index */
  3057. {
  3058. ulint sum = 0;
  3059. ulint i;
  3060. for (i = 0; i < dict_index_get_n_fields(index); i++) {
  3061. sum += dtype_get_fixed_size(dict_index_get_nth_type(index, i));
  3062. }
  3063. if (sum > 127) {
  3064. sum += 2 * dict_index_get_n_fields(index);
  3065. } else {
  3066. sum += dict_index_get_n_fields(index);
  3067. }
  3068. sum += REC_N_EXTRA_BYTES;
  3069. return(sum);
  3070. }
  3071. /*************************************************************************
  3072. Calculates new estimates for table and index statistics. The statistics
  3073. are used in query optimization. */
  3074. void
  3075. dict_update_statistics_low(
  3076. /*=======================*/
  3077. dict_table_t* table, /* in: table */
  3078. ibool has_dict_mutex __attribute__((unused)))
  3079.                                         /* in: TRUE if the caller has the
  3080. dictionary mutex */
  3081. {
  3082. dict_index_t* index;
  3083. ulint size;
  3084. ulint sum_of_index_sizes = 0;
  3085. if (table->ibd_file_missing) {
  3086. ut_print_timestamp(stderr);
  3087. fprintf(stderr,
  3088. "  InnoDB: cannot calculate statistics for table %sn"
  3089. "InnoDB: because the .ibd file is missing.  For help, please refer ton"
  3090. "InnoDB: "
  3091. "http://dev.mysql.com/doc/mysql/en/InnoDB_troubleshooting_datadict.htmln",
  3092. table->name);
  3093. return;
  3094. }
  3095. /* If we have set a high innodb_force_recovery level, do not calculate
  3096. statistics, as a badly corrupted index can cause a crash in it. */
  3097. if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
  3098. return;
  3099. }
  3100. /* Find out the sizes of the indexes and how many different values
  3101. for the key they approximately have */
  3102. index = dict_table_get_first_index(table);
  3103. if (index == NULL) {
  3104. /* Table definition is corrupt */
  3105. return;
  3106. }
  3107. while (index) {
  3108. size = btr_get_size(index, BTR_TOTAL_SIZE);
  3109. index->stat_index_size = size;
  3110. sum_of_index_sizes += size;
  3111. size = btr_get_size(index, BTR_N_LEAF_PAGES);
  3112. if (size == 0) {
  3113. /* The root node of the tree is a leaf */
  3114. size = 1;
  3115. }
  3116. index->stat_n_leaf_pages = size;
  3117. btr_estimate_number_of_different_key_vals(index);
  3118. index = dict_table_get_next_index(index);
  3119. }
  3120. index = dict_table_get_first_index(table);
  3121. table->stat_n_rows = index->stat_n_diff_key_vals[
  3122. dict_index_get_n_unique(index)];
  3123. table->stat_clustered_index_size = index->stat_index_size;
  3124. table->stat_sum_of_other_index_sizes = sum_of_index_sizes
  3125. - index->stat_index_size;
  3126. table->stat_initialized = TRUE;
  3127.         table->stat_modified_counter = 0;
  3128. }
  3129. /*************************************************************************
  3130. Calculates new estimates for table and index statistics. The statistics
  3131. are used in query optimization. */
  3132. void
  3133. dict_update_statistics(
  3134. /*===================*/
  3135. dict_table_t* table) /* in: table */
  3136. {
  3137. dict_update_statistics_low(table, FALSE);
  3138. }
  3139. /**************************************************************************
  3140. Prints info of a foreign key constraint. */
  3141. static
  3142. void
  3143. dict_foreign_print_low(
  3144. /*===================*/
  3145. dict_foreign_t* foreign) /* in: foreign key constraint */
  3146. {
  3147. ulint i;
  3148. #ifdef UNIV_SYNC_DEBUG
  3149. ut_ad(mutex_own(&(dict_sys->mutex)));
  3150. #endif /* UNIV_SYNC_DEBUG */
  3151. fprintf(stderr, "  FOREIGN KEY CONSTRAINT %s: %s (",
  3152. foreign->id, foreign->foreign_table_name);
  3153. for (i = 0; i < foreign->n_fields; i++) {
  3154. fprintf(stderr, " %s", foreign->foreign_col_names[i]);
  3155. }
  3156. fprintf(stderr, " )n"
  3157. "             REFERENCES %s (",
  3158. foreign->referenced_table_name);
  3159. for (i = 0; i < foreign->n_fields; i++) {
  3160. fprintf(stderr, " %s", foreign->referenced_col_names[i]);
  3161. }
  3162. fputs(" )n", stderr);
  3163. }
  3164. /**************************************************************************
  3165. Prints a table data. */
  3166. void
  3167. dict_table_print(
  3168. /*=============*/
  3169. dict_table_t* table) /* in: table */
  3170. {
  3171. mutex_enter(&(dict_sys->mutex));
  3172. dict_table_print_low(table);
  3173. mutex_exit(&(dict_sys->mutex));
  3174. }
  3175. /**************************************************************************
  3176. Prints a table data when we know the table name. */
  3177. void
  3178. dict_table_print_by_name(
  3179. /*=====================*/
  3180. const char* name)
  3181. {
  3182. dict_table_t* table;
  3183. mutex_enter(&(dict_sys->mutex));
  3184. table = dict_table_get_low(name);
  3185. ut_a(table);
  3186. dict_table_print_low(table);
  3187. mutex_exit(&(dict_sys->mutex));
  3188. }
  3189. /**************************************************************************
  3190. Prints a table data. */
  3191. void
  3192. dict_table_print_low(
  3193. /*=================*/
  3194. dict_table_t* table) /* in: table */
  3195. {
  3196. dict_index_t* index;
  3197. dict_foreign_t* foreign;
  3198. ulint i;
  3199. #ifdef UNIV_SYNC_DEBUG
  3200. ut_ad(mutex_own(&(dict_sys->mutex)));
  3201. #endif /* UNIV_SYNC_DEBUG */
  3202. dict_update_statistics_low(table, TRUE);
  3203. fprintf(stderr,
  3204. "--------------------------------------n"
  3205. "TABLE: name %s, id %lu %lu, columns %lu, indexes %lu, appr.rows %lun"
  3206. "  COLUMNS: ",
  3207. table->name,
  3208. (ulong) ut_dulint_get_high(table->id),
  3209. (ulong) ut_dulint_get_low(table->id),
  3210. (ulong) table->n_cols,
  3211.         (ulong) UT_LIST_GET_LEN(table->indexes),
  3212. (ulong) table->stat_n_rows);
  3213. for (i = 0; i < table->n_cols - 1; i++) {
  3214. dict_col_print_low(dict_table_get_nth_col(table, i));
  3215. fputs("; ", stderr);
  3216. }
  3217. putc('n', stderr);
  3218. index = UT_LIST_GET_FIRST(table->indexes);
  3219. while (index != NULL) {
  3220. dict_index_print_low(index);
  3221. index = UT_LIST_GET_NEXT(indexes, index);
  3222. }
  3223. foreign = UT_LIST_GET_FIRST(table->foreign_list);
  3224. while (foreign != NULL) {
  3225. dict_foreign_print_low(foreign);
  3226. foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
  3227. }
  3228. foreign = UT_LIST_GET_FIRST(table->referenced_list);
  3229. while (foreign != NULL) {
  3230. dict_foreign_print_low(foreign);
  3231. foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
  3232. }
  3233. }
  3234. /**************************************************************************
  3235. Prints a column data. */
  3236. static
  3237. void
  3238. dict_col_print_low(
  3239. /*===============*/
  3240. dict_col_t* col) /* in: column */
  3241. {
  3242. dtype_t* type;
  3243. #ifdef UNIV_SYNC_DEBUG
  3244. ut_ad(mutex_own(&(dict_sys->mutex)));
  3245. #endif /* UNIV_SYNC_DEBUG */
  3246. type = dict_col_get_type(col);
  3247. fprintf(stderr, "%s: ", col->name);
  3248. dtype_print(type);
  3249. }
  3250. /**************************************************************************
  3251. Prints an index data. */
  3252. static
  3253. void
  3254. dict_index_print_low(
  3255. /*=================*/
  3256. dict_index_t* index) /* in: index */
  3257. {
  3258. dict_tree_t* tree;
  3259. ib_longlong n_vals;
  3260. ulint i;
  3261. #ifdef UNIV_SYNC_DEBUG
  3262. ut_ad(mutex_own(&(dict_sys->mutex)));
  3263. #endif /* UNIV_SYNC_DEBUG */
  3264. tree = index->tree;
  3265. if (index->n_user_defined_cols > 0) {
  3266. n_vals = index->stat_n_diff_key_vals[
  3267. index->n_user_defined_cols];
  3268. } else {
  3269. n_vals = index->stat_n_diff_key_vals[1];
  3270. }
  3271. fprintf(stderr,
  3272. "  INDEX: name %s, id %lu %lu, fields %lu/%lu, type %lun"
  3273. "   root page %lu, appr.key vals %lu,"
  3274. " leaf pages %lu, size pages %lun"
  3275. "   FIELDS: ",
  3276. index->name,
  3277. (ulong) ut_dulint_get_high(tree->id),
  3278. (ulong) ut_dulint_get_low(tree->id),
  3279. (ulong) index->n_user_defined_cols,
  3280. (ulong) index->n_fields, (ulong) index->type,
  3281. (ulong) tree->page,
  3282. (ulong) n_vals,
  3283. (ulong) index->stat_n_leaf_pages,
  3284. (ulong) index->stat_index_size);
  3285. for (i = 0; i < index->n_fields; i++) {
  3286. dict_field_print_low(dict_index_get_nth_field(index, i));
  3287. }
  3288. putc('n', stderr);
  3289. /* btr_print_size(tree); */
  3290. /* btr_print_tree(tree, 7); */
  3291. }
  3292. /**************************************************************************
  3293. Prints a field data. */
  3294. static
  3295. void
  3296. dict_field_print_low(
  3297. /*=================*/
  3298. dict_field_t* field) /* in: field */
  3299. {
  3300. #ifdef UNIV_SYNC_DEBUG
  3301. ut_ad(mutex_own(&(dict_sys->mutex)));
  3302. #endif /* UNIV_SYNC_DEBUG */
  3303. fprintf(stderr, " %s", field->name);
  3304. if (field->prefix_len != 0) {
  3305. fprintf(stderr, "(%lu)", (ulong) field->prefix_len);
  3306. }
  3307. }
  3308. /**************************************************************************
  3309. Outputs info on a foreign key of a table in a format suitable for
  3310. CREATE TABLE. */
  3311. void
  3312. dict_print_info_on_foreign_key_in_create_format(
  3313. /*============================================*/
  3314. FILE* file, /* in: file where to print */
  3315. trx_t* trx, /* in: transaction */
  3316. dict_foreign_t* foreign)/* in: foreign key constraint */
  3317. {
  3318. const char* stripped_id;
  3319. ulint i;
  3320. if (strchr(foreign->id, '/')) {
  3321. /* Strip the preceding database name from the constraint id */
  3322. stripped_id = foreign->id + 1
  3323. + dict_get_db_name_len(foreign->id);
  3324. } else {
  3325. stripped_id = foreign->id;
  3326. }
  3327. fputs(",n  CONSTRAINT ", file);
  3328. ut_print_name(file, trx, stripped_id);
  3329. fputs(" FOREIGN KEY (", file);
  3330. for (i = 0;;) {
  3331. ut_print_name(file, trx, foreign->foreign_col_names[i]);
  3332. if (++i < foreign->n_fields) {
  3333. fputs(", ", file);
  3334.         } else {
  3335. break;
  3336. }
  3337. }
  3338. fputs(") REFERENCES ", file);
  3339. if (dict_tables_have_same_db(foreign->foreign_table_name,
  3340. foreign->referenced_table_name)) {
  3341. /* Do not print the database name of the referenced table */
  3342. ut_print_name(file, trx, dict_remove_db_name(
  3343. foreign->referenced_table_name));
  3344. } else {
  3345. /* Look for the '/' in the table name */
  3346. i = 0;
  3347. while (foreign->referenced_table_name[i] != '/') {
  3348. i++;
  3349. }
  3350. ut_print_namel(file, trx, foreign->referenced_table_name, i);
  3351. putc('.', file);
  3352. ut_print_name(file, trx,
  3353. foreign->referenced_table_name + i + 1);
  3354. }
  3355. putc(' ', file);
  3356. putc('(', file);
  3357. for (i = 0;;) {
  3358. ut_print_name(file, trx, foreign->referenced_col_names[i]);
  3359. if (++i < foreign->n_fields) {
  3360. fputs(", ", file);
  3361. } else {
  3362. break;
  3363. }
  3364. }
  3365. putc(')', file);
  3366. if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE) {
  3367. fputs(" ON DELETE CASCADE", file);
  3368. }
  3369. if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL) {
  3370. fputs(" ON DELETE SET NULL", file);
  3371. }
  3372. if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION) {
  3373. fputs(" ON DELETE NO ACTION", file);
  3374. }
  3375. if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE) {
  3376. fputs(" ON UPDATE CASCADE", file);
  3377. }
  3378. if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL) {
  3379. fputs(" ON UPDATE SET NULL", file);
  3380. }
  3381. if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION) {
  3382. fputs(" ON UPDATE NO ACTION", file);
  3383. }
  3384. }
  3385. /**************************************************************************
  3386. Outputs info on foreign keys of a table. */
  3387. void
  3388. dict_print_info_on_foreign_keys(
  3389. /*============================*/
  3390. ibool create_table_format, /* in: if TRUE then print in
  3391. a format suitable to be inserted into
  3392. a CREATE TABLE, otherwise in the format
  3393. of SHOW TABLE STATUS */
  3394. FILE* file, /* in: file where to print */
  3395. trx_t* trx, /* in: transaction */
  3396. dict_table_t* table) /* in: table */
  3397. {
  3398. dict_foreign_t* foreign;
  3399. mutex_enter(&(dict_sys->mutex));
  3400. foreign = UT_LIST_GET_FIRST(table->foreign_list);
  3401. if (foreign == NULL) {
  3402. mutex_exit(&(dict_sys->mutex));
  3403. return;
  3404. }
  3405. while (foreign != NULL) {
  3406. if (create_table_format) {
  3407. dict_print_info_on_foreign_key_in_create_format(
  3408. file, trx, foreign);
  3409. } else {
  3410. ulint i;
  3411. fputs("; (", file);
  3412. for (i = 0; i < foreign->n_fields; i++) {
  3413. if (i) {
  3414. putc(' ', file);
  3415. }
  3416. ut_print_name(file, trx,
  3417. foreign->foreign_col_names[i]);
  3418. }
  3419. fputs(") REFER ", file);
  3420. ut_print_name(file, trx,
  3421. foreign->referenced_table_name);
  3422. putc('(', file);
  3423. for (i = 0; i < foreign->n_fields; i++) {
  3424. if (i) {
  3425. putc(' ', file);
  3426. }
  3427. ut_print_name(file, trx,
  3428. foreign->referenced_col_names[i]);
  3429. }
  3430. putc(')', file);
  3431. if (foreign->type == DICT_FOREIGN_ON_DELETE_CASCADE) {
  3432. fputs(" ON DELETE CASCADE", file);
  3433. }
  3434. if (foreign->type == DICT_FOREIGN_ON_DELETE_SET_NULL) {
  3435. fputs(" ON DELETE SET NULL", file);
  3436. }
  3437. if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION) {
  3438. fputs(" ON DELETE NO ACTION", file);
  3439. }
  3440. if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE) {
  3441. fputs(" ON UPDATE CASCADE", file);
  3442. }
  3443. if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL) {
  3444. fputs(" ON UPDATE SET NULL", file);
  3445. }
  3446. if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION) {
  3447. fputs(" ON UPDATE NO ACTION", file);
  3448. }
  3449. }
  3450. foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
  3451. }
  3452. mutex_exit(&(dict_sys->mutex));
  3453. }
  3454. /************************************************************************
  3455. Displays the names of the index and the table. */
  3456. void
  3457. dict_index_name_print(
  3458. /*==================*/
  3459. FILE* file, /* in: output stream */
  3460. trx_t* trx, /* in: transaction */
  3461. const dict_index_t* index) /* in: index to print */
  3462. {
  3463. fputs("index ", file);
  3464. ut_print_name(file, trx, index->name);
  3465. fputs(" of table ", file);
  3466. ut_print_name(file, trx, index->table_name);
  3467. }