00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00026 #include "dict0dict.h"
00027
00028 #ifdef UNIV_NONINL
00029 #include "dict0dict.ic"
00030 #endif
00031
00033 UNIV_INTERN dict_index_t* dict_ind_redundant;
00035 UNIV_INTERN dict_index_t* dict_ind_compact;
00036
00037 #ifndef UNIV_HOTBACKUP
00038 #include "buf0buf.h"
00039 #include "data0type.h"
00040 #include "mach0data.h"
00041 #include "dict0boot.h"
00042 #include "dict0mem.h"
00043 #include "dict0crea.h"
00044 #include "trx0undo.h"
00045 #include "btr0btr.h"
00046 #include "btr0cur.h"
00047 #include "btr0sea.h"
00048 #include "page0zip.h"
00049 #include "page0page.h"
00050 #include "pars0pars.h"
00051 #include "pars0sym.h"
00052 #include "que0que.h"
00053 #include "rem0cmp.h"
00054 #include "row0merge.h"
00055 #include "ha_prototypes.h"
00056
00057 #include <ctype.h>
00058
00059 #include <drizzled/session.h>
00060
00062 UNIV_INTERN dict_sys_t* dict_sys = NULL;
00063
00072 UNIV_INTERN rw_lock_t dict_operation_lock;
00073
00074
00075 #ifdef UNIV_PFS_RWLOCK
00076 UNIV_INTERN mysql_pfs_key_t dict_operation_lock_key;
00077 UNIV_INTERN mysql_pfs_key_t index_tree_rw_lock_key;
00078 #endif
00079
00080 #ifdef UNIV_PFS_MUTEX
00081 UNIV_INTERN mysql_pfs_key_t dict_sys_mutex_key;
00082 UNIV_INTERN mysql_pfs_key_t dict_foreign_err_mutex_key;
00083 #endif
00084
00085 #define DICT_HEAP_SIZE 100
00087 #define DICT_POOL_PER_TABLE_HASH 512
00089 #define DICT_POOL_PER_VARYING 4
00093 static char dict_ibfk[] = "_ibfk_";
00094
00105 #define DICT_TABLE_STATS_LATCHES_SIZE 64
00106 static rw_lock_t dict_table_stats_latches[DICT_TABLE_STATS_LATCHES_SIZE];
00107
00108
00112 static
00113 ibool
00114 dict_index_find_cols(
00115
00116 dict_table_t* table,
00117 dict_index_t* index);
00118
00122 static
00123 dict_index_t*
00124 dict_index_build_internal_clust(
00125
00126 const dict_table_t* table,
00127 dict_index_t* index);
00129
00133 static
00134 dict_index_t*
00135 dict_index_build_internal_non_clust(
00136
00137 const dict_table_t* table,
00138 dict_index_t* index);
00140
00142 static
00143 void
00144 dict_foreign_remove_from_cache(
00145
00146 dict_foreign_t* foreign);
00147
00149 static
00150 void
00151 dict_col_print_low(
00152
00153 const dict_table_t* table,
00154 const dict_col_t* col);
00155
00157 static
00158 void
00159 dict_index_print_low(
00160
00161 dict_index_t* index);
00162
00164 static
00165 void
00166 dict_field_print_low(
00167
00168 const dict_field_t* field);
00169
00171 static
00172 void
00173 dict_foreign_free(
00174
00175 dict_foreign_t* foreign);
00177
00178
00179 UNIV_INTERN FILE* dict_foreign_err_file = NULL;
00180
00181 UNIV_INTERN mutex_t dict_foreign_err_mutex;
00182
00183
00185 UNIV_INTERN
00186 void
00187 dict_casedn_str(
00188
00189 char* a)
00190 {
00191 innobase_casedn_str(a);
00192 }
00193
00194
00197 UNIV_INTERN
00198 ibool
00199 dict_tables_have_same_db(
00200
00201 const char* name1,
00203 const char* name2)
00205 {
00206 for (; *name1 == *name2; name1++, name2++) {
00207 if (*name1 == '/') {
00208 return(TRUE);
00209 }
00210 ut_a(*name1);
00211 }
00212 return(FALSE);
00213 }
00214
00215
00218 UNIV_INTERN
00219 const char*
00220 dict_remove_db_name(
00221
00222 const char* name)
00224 {
00225 const char* s = strchr(name, '/');
00226 ut_a(s);
00227
00228 return(s + 1);
00229 }
00230
00231
00234 UNIV_INTERN
00235 ulint
00236 dict_get_db_name_len(
00237
00238 const char* name)
00240 {
00241 const char* s;
00242 s = strchr(name, '/');
00243 ut_a(s);
00244 return(s - name);
00245 }
00246
00247
00249 UNIV_INTERN
00250 void
00251 dict_mutex_enter_for_mysql(void)
00252
00253 {
00254 mutex_enter(&(dict_sys->mutex));
00255 }
00256
00257
00259 UNIV_INTERN
00260 void
00261 dict_mutex_exit_for_mysql(void)
00262
00263 {
00264 mutex_exit(&(dict_sys->mutex));
00265 }
00266
00268 #define GET_TABLE_STATS_LATCH(table) \
00269 (&dict_table_stats_latches[ut_fold_ull(table->id) \
00270 % DICT_TABLE_STATS_LATCHES_SIZE])
00271
00272
00276 UNIV_INTERN
00277 void
00278 dict_table_stats_lock(
00279
00280 const dict_table_t* table,
00281 ulint latch_mode)
00283 {
00284 ut_ad(table != NULL);
00285 ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
00286
00287 switch (latch_mode) {
00288 case RW_S_LATCH:
00289 rw_lock_s_lock(GET_TABLE_STATS_LATCH(table));
00290 break;
00291 case RW_X_LATCH:
00292 rw_lock_x_lock(GET_TABLE_STATS_LATCH(table));
00293 break;
00294 case RW_NO_LATCH:
00295
00296 default:
00297 ut_error;
00298 }
00299 }
00300
00301
00303 UNIV_INTERN
00304 void
00305 dict_table_stats_unlock(
00306
00307 const dict_table_t* table,
00308 ulint latch_mode)
00310 {
00311 ut_ad(table != NULL);
00312 ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
00313
00314 switch (latch_mode) {
00315 case RW_S_LATCH:
00316 rw_lock_s_unlock(GET_TABLE_STATS_LATCH(table));
00317 break;
00318 case RW_X_LATCH:
00319 rw_lock_x_unlock(GET_TABLE_STATS_LATCH(table));
00320 break;
00321 case RW_NO_LATCH:
00322
00323 default:
00324 ut_error;
00325 }
00326 }
00327
00328
00330 UNIV_INTERN
00331 void
00332 dict_table_decrement_handle_count(
00333
00334 dict_table_t* table,
00335 ibool dict_locked)
00336 {
00337 if (!dict_locked) {
00338 mutex_enter(&dict_sys->mutex);
00339 }
00340
00341 ut_ad(mutex_own(&dict_sys->mutex));
00342 ut_a(table->n_mysql_handles_opened > 0);
00343
00344 table->n_mysql_handles_opened--;
00345
00346 if (!dict_locked) {
00347 mutex_exit(&dict_sys->mutex);
00348 }
00349 }
00350 #endif
00351
00352
00356 UNIV_INTERN
00357 const char*
00358 dict_table_get_col_name(
00359
00360 const dict_table_t* table,
00361 ulint col_nr)
00362 {
00363 ulint i;
00364 const char* s;
00365
00366 ut_ad(table);
00367 ut_ad(col_nr < table->n_def);
00368 ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
00369
00370 s = table->col_names;
00371 if (s) {
00372 for (i = 0; i < col_nr; i++) {
00373 s += strlen(s) + 1;
00374 }
00375 }
00376
00377 return(s);
00378 }
00379
00380 #ifndef UNIV_HOTBACKUP
00381
00383 UNIV_INTERN
00384 void
00385 dict_table_autoinc_lock(
00386
00387 dict_table_t* table)
00388 {
00389 mutex_enter(&table->autoinc_mutex);
00390 }
00391
00392
00394 UNIV_INTERN
00395 void
00396 dict_table_autoinc_initialize(
00397
00398 dict_table_t* table,
00399 ib_uint64_t value)
00400 {
00401 ut_ad(mutex_own(&table->autoinc_mutex));
00402
00403 table->autoinc = value;
00404 }
00405
00406
00410 UNIV_INTERN
00411 ib_uint64_t
00412 dict_table_autoinc_read(
00413
00414 const dict_table_t* table)
00415 {
00416 ut_ad(mutex_own(&table->autoinc_mutex));
00417
00418 return(table->autoinc);
00419 }
00420
00421
00424 UNIV_INTERN
00425 void
00426 dict_table_autoinc_update_if_greater(
00427
00428
00429 dict_table_t* table,
00430 ib_uint64_t value)
00431 {
00432 ut_ad(mutex_own(&table->autoinc_mutex));
00433
00434 if (value > table->autoinc) {
00435
00436 table->autoinc = value;
00437 }
00438 }
00439
00440
00442 UNIV_INTERN
00443 void
00444 dict_table_autoinc_unlock(
00445
00446 dict_table_t* table)
00447 {
00448 mutex_exit(&table->autoinc_mutex);
00449 }
00450
00451
00455 UNIV_INTERN
00456 dict_index_t*
00457 dict_index_get_on_id_low(
00458
00459 dict_table_t* table,
00460 index_id_t id)
00461 {
00462 dict_index_t* index;
00463
00464 index = dict_table_get_first_index(table);
00465
00466 while (index) {
00467 if (id == index->id) {
00468
00469
00470 return(index);
00471 }
00472
00473 index = dict_table_get_next_index(index);
00474 }
00475
00476 return(NULL);
00477 }
00478 #endif
00479
00480
00484 UNIV_INTERN
00485 ulint
00486 dict_index_get_nth_col_pos(
00487
00488 const dict_index_t* index,
00489 ulint n)
00490 {
00491 const dict_field_t* field;
00492 const dict_col_t* col;
00493 ulint pos;
00494 ulint n_fields;
00495
00496 ut_ad(index);
00497 ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
00498
00499 col = dict_table_get_nth_col(index->table, n);
00500
00501 if (dict_index_is_clust(index)) {
00502
00503 return(dict_col_get_clust_pos(col, index));
00504 }
00505
00506 n_fields = dict_index_get_n_fields(index);
00507
00508 for (pos = 0; pos < n_fields; pos++) {
00509 field = dict_index_get_nth_field(index, pos);
00510
00511 if (col == field->col && field->prefix_len == 0) {
00512
00513 return(pos);
00514 }
00515 }
00516
00517 return(ULINT_UNDEFINED);
00518 }
00519
00520 #ifndef UNIV_HOTBACKUP
00521
00524 UNIV_INTERN
00525 ibool
00526 dict_index_contains_col_or_prefix(
00527
00528 const dict_index_t* index,
00529 ulint n)
00530 {
00531 const dict_field_t* field;
00532 const dict_col_t* col;
00533 ulint pos;
00534 ulint n_fields;
00535
00536 ut_ad(index);
00537 ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
00538
00539 if (dict_index_is_clust(index)) {
00540
00541 return(TRUE);
00542 }
00543
00544 col = dict_table_get_nth_col(index->table, n);
00545
00546 n_fields = dict_index_get_n_fields(index);
00547
00548 for (pos = 0; pos < n_fields; pos++) {
00549 field = dict_index_get_nth_field(index, pos);
00550
00551 if (col == field->col) {
00552
00553 return(TRUE);
00554 }
00555 }
00556
00557 return(FALSE);
00558 }
00559
00560
00567 UNIV_INTERN
00568 ulint
00569 dict_index_get_nth_field_pos(
00570
00571 const dict_index_t* index,
00572 const dict_index_t* index2,
00573 ulint n)
00574 {
00575 const dict_field_t* field;
00576 const dict_field_t* field2;
00577 ulint n_fields;
00578 ulint pos;
00579
00580 ut_ad(index);
00581 ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
00582
00583 field2 = dict_index_get_nth_field(index2, n);
00584
00585 n_fields = dict_index_get_n_fields(index);
00586
00587 for (pos = 0; pos < n_fields; pos++) {
00588 field = dict_index_get_nth_field(index, pos);
00589
00590 if (field->col == field2->col
00591 && (field->prefix_len == 0
00592 || (field->prefix_len >= field2->prefix_len
00593 && field2->prefix_len != 0))) {
00594
00595 return(pos);
00596 }
00597 }
00598
00599 return(ULINT_UNDEFINED);
00600 }
00601
00602
00605 UNIV_INTERN
00606 dict_table_t*
00607 dict_table_get_on_id(
00608
00609 table_id_t table_id,
00610 trx_t* trx)
00611 {
00612 dict_table_t* table;
00613
00614 if (trx->dict_operation_lock_mode == RW_X_LATCH) {
00615
00616
00617
00618
00619 ut_ad(mutex_own(&dict_sys->mutex));
00620
00621 return(dict_table_get_on_id_low(table_id));
00622 }
00623
00624 mutex_enter(&(dict_sys->mutex));
00625
00626 table = dict_table_get_on_id_low(table_id);
00627
00628 mutex_exit(&(dict_sys->mutex));
00629
00630 return(table);
00631 }
00632
00633
00636 UNIV_INTERN
00637 ulint
00638 dict_table_get_nth_col_pos(
00639
00640 const dict_table_t* table,
00641 ulint n)
00642 {
00643 return(dict_index_get_nth_col_pos(dict_table_get_first_index(table),
00644 n));
00645 }
00646
00647
00651 UNIV_INTERN
00652 ibool
00653 dict_table_col_in_clustered_key(
00654
00655 const dict_table_t* table,
00656 ulint n)
00657 {
00658 const dict_index_t* index;
00659 const dict_field_t* field;
00660 const dict_col_t* col;
00661 ulint pos;
00662 ulint n_fields;
00663
00664 ut_ad(table);
00665
00666 col = dict_table_get_nth_col(table, n);
00667
00668 index = dict_table_get_first_index(table);
00669
00670 n_fields = dict_index_get_n_unique(index);
00671
00672 for (pos = 0; pos < n_fields; pos++) {
00673 field = dict_index_get_nth_field(index, pos);
00674
00675 if (col == field->col) {
00676
00677 return(TRUE);
00678 }
00679 }
00680
00681 return(FALSE);
00682 }
00683
00684
00686 UNIV_INTERN
00687 void
00688 dict_init(void)
00689
00690 {
00691 int i;
00692
00693 dict_sys = static_cast<dict_sys_t *>(mem_alloc(sizeof(dict_sys_t)));
00694
00695 mutex_create(dict_sys_mutex_key, &dict_sys->mutex, SYNC_DICT);
00696
00697 dict_sys->table_hash = hash_create(buf_pool_get_curr_size()
00698 / (DICT_POOL_PER_TABLE_HASH
00699 * UNIV_WORD_SIZE));
00700 dict_sys->table_id_hash = hash_create(buf_pool_get_curr_size()
00701 / (DICT_POOL_PER_TABLE_HASH
00702 * UNIV_WORD_SIZE));
00703 dict_sys->size = 0;
00704
00705 UT_LIST_INIT(dict_sys->table_LRU);
00706
00707 rw_lock_create(dict_operation_lock_key,
00708 &dict_operation_lock, SYNC_DICT_OPERATION);
00709
00710 dict_foreign_err_file = os_file_create_tmpfile();
00711 ut_a(dict_foreign_err_file);
00712
00713 mutex_create(dict_foreign_err_mutex_key,
00714 &dict_foreign_err_mutex, SYNC_ANY_LATCH);
00715
00716 for (i = 0; i < DICT_TABLE_STATS_LATCHES_SIZE; i++) {
00717 rw_lock_create(PFS_NOT_INSTRUMENTED,
00718 &dict_table_stats_latches[i], SYNC_INDEX_TREE);
00719 }
00720 }
00721
00722
00728 UNIV_INTERN
00729 dict_table_t*
00730 dict_table_get(
00731
00732 const char* table_name,
00733 ibool inc_mysql_count)
00735 {
00736 dict_table_t* table;
00737
00738 mutex_enter(&(dict_sys->mutex));
00739
00740 table = dict_table_get_low(table_name);
00741
00742 if (inc_mysql_count && table) {
00743 table->n_mysql_handles_opened++;
00744 }
00745
00746 mutex_exit(&(dict_sys->mutex));
00747
00748 if (table != NULL) {
00749
00750
00751
00752 dict_update_statistics(table, TRUE
00753 );
00754 }
00755
00756 return(table);
00757 }
00758 #endif
00759
00760
00762 UNIV_INTERN
00763 void
00764 dict_table_add_system_columns(
00765
00766 dict_table_t* table,
00767 mem_heap_t* heap)
00768 {
00769 ut_ad(table);
00770 ut_ad(table->n_def == table->n_cols - DATA_N_SYS_COLS);
00771 ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
00772 ut_ad(!table->cached);
00773
00774
00775
00776
00777
00778
00779
00780 dict_mem_table_add_col(table, heap, "DB_ROW_ID", DATA_SYS,
00781 DATA_ROW_ID | DATA_NOT_NULL,
00782 DATA_ROW_ID_LEN);
00783 #if DATA_ROW_ID != 0
00784 #error "DATA_ROW_ID != 0"
00785 #endif
00786 dict_mem_table_add_col(table, heap, "DB_TRX_ID", DATA_SYS,
00787 DATA_TRX_ID | DATA_NOT_NULL,
00788 DATA_TRX_ID_LEN);
00789 #if DATA_TRX_ID != 1
00790 #error "DATA_TRX_ID != 1"
00791 #endif
00792 dict_mem_table_add_col(table, heap, "DB_ROLL_PTR", DATA_SYS,
00793 DATA_ROLL_PTR | DATA_NOT_NULL,
00794 DATA_ROLL_PTR_LEN);
00795 #if DATA_ROLL_PTR != 2
00796 #error "DATA_ROLL_PTR != 2"
00797 #endif
00798
00799
00800
00801 #if DATA_N_SYS_COLS != 3
00802 #error "DATA_N_SYS_COLS != 3"
00803 #endif
00804 }
00805
00806 #ifndef UNIV_HOTBACKUP
00807
00809 UNIV_INTERN
00810 void
00811 dict_table_add_to_cache(
00812
00813 dict_table_t* table,
00814 mem_heap_t* heap)
00815 {
00816 ulint fold;
00817 ulint id_fold;
00818 ulint i;
00819 ulint row_len;
00820
00821
00822 #define BIG_ROW_SIZE 1024
00823
00824 ut_ad(mutex_own(&(dict_sys->mutex)));
00825
00826 dict_table_add_system_columns(table, heap);
00827
00828 table->cached = TRUE;
00829
00830 fold = ut_fold_string(table->name);
00831 id_fold = ut_fold_ull(table->id);
00832
00833 row_len = 0;
00834 for (i = 0; i < table->n_def; i++) {
00835 ulint col_len = dict_col_get_max_size(
00836 dict_table_get_nth_col(table, i));
00837
00838 row_len += col_len;
00839
00840
00841
00842 if (row_len >= BIG_ROW_SIZE || col_len >= BIG_ROW_SIZE) {
00843 row_len = BIG_ROW_SIZE;
00844
00845 break;
00846 }
00847 }
00848
00849 table->big_rows = row_len >= BIG_ROW_SIZE;
00850
00851
00852 {
00853 dict_table_t* table2;
00854 HASH_SEARCH(name_hash, dict_sys->table_hash, fold,
00855 dict_table_t*, table2, ut_ad(table2->cached),
00856 ut_strcmp(table2->name, table->name) == 0);
00857 ut_a(table2 == NULL);
00858
00859 #ifdef UNIV_DEBUG
00860
00861 HASH_SEARCH_ALL(name_hash, dict_sys->table_hash,
00862 dict_table_t*, table2, ut_ad(table2->cached),
00863 table2 == table);
00864 ut_ad(table2 == NULL);
00865 #endif
00866 }
00867
00868
00869 {
00870 dict_table_t* table2;
00871 HASH_SEARCH(id_hash, dict_sys->table_id_hash, id_fold,
00872 dict_table_t*, table2, ut_ad(table2->cached),
00873 table2->id == table->id);
00874 ut_a(table2 == NULL);
00875
00876 #ifdef UNIV_DEBUG
00877
00878 HASH_SEARCH_ALL(id_hash, dict_sys->table_id_hash,
00879 dict_table_t*, table2, ut_ad(table2->cached),
00880 table2 == table);
00881 ut_ad(table2 == NULL);
00882 #endif
00883 }
00884
00885
00886 HASH_INSERT(dict_table_t, name_hash, dict_sys->table_hash, fold,
00887 table);
00888
00889
00890 HASH_INSERT(dict_table_t, id_hash, dict_sys->table_id_hash, id_fold,
00891 table);
00892
00893 UT_LIST_ADD_FIRST(table_LRU, dict_sys->table_LRU, table);
00894
00895 dict_sys->size += mem_heap_get_size(table->heap)
00896 + strlen(table->name) + 1;
00897 }
00898
00899
00904 UNIV_INTERN
00905 dict_index_t*
00906 dict_index_find_on_id_low(
00907
00908 index_id_t id)
00909 {
00910 dict_table_t* table;
00911 dict_index_t* index;
00912
00913 table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
00914
00915 while (table) {
00916 index = dict_table_get_first_index(table);
00917
00918 while (index) {
00919 if (id == index->id) {
00920
00921
00922 return(index);
00923 }
00924
00925 index = dict_table_get_next_index(index);
00926 }
00927
00928 table = UT_LIST_GET_NEXT(table_LRU, table);
00929 }
00930
00931 return(NULL);
00932 }
00933
00934
00937 UNIV_INTERN
00938 ibool
00939 dict_table_rename_in_cache(
00940
00941 dict_table_t* table,
00942 const char* new_name,
00943 ibool rename_also_foreigns)
00946 {
00947 dict_foreign_t* foreign;
00948 dict_index_t* index;
00949 ulint fold;
00950 char old_name[MAX_TABLE_NAME_LEN + 1];
00951
00952 ut_ad(table);
00953 ut_ad(mutex_own(&(dict_sys->mutex)));
00954
00955
00956 if (strlen(table->name) + 1 <= sizeof(old_name)) {
00957 memcpy(old_name, table->name, strlen(table->name) + 1);
00958 } else {
00959 ut_print_timestamp(stderr);
00960 fprintf(stderr, "InnoDB: too long table name: '%s', "
00961 "max length is %d\n", table->name,
00962 MAX_TABLE_NAME_LEN);
00963 ut_error;
00964 }
00965
00966 fold = ut_fold_string(new_name);
00967
00968
00969 {
00970 dict_table_t* table2;
00971 HASH_SEARCH(name_hash, dict_sys->table_hash, fold,
00972 dict_table_t*, table2, ut_ad(table2->cached),
00973 (ut_strcmp(table2->name, new_name) == 0));
00974 if (UNIV_LIKELY_NULL(table2)) {
00975 ut_print_timestamp(stderr);
00976 fputs(" InnoDB: Error: dictionary cache"
00977 " already contains a table ", stderr);
00978 ut_print_name(stderr, NULL, TRUE, new_name);
00979 fputs("\n"
00980 "InnoDB: cannot rename table ", stderr);
00981 ut_print_name(stderr, NULL, TRUE, old_name);
00982 putc('\n', stderr);
00983 return(FALSE);
00984 }
00985 }
00986
00987
00988
00989
00990 if (table->space != 0) {
00991 if (table->dir_path_of_temp_table != NULL) {
00992 ut_print_timestamp(stderr);
00993 fputs(" InnoDB: Error: trying to rename a"
00994 " TEMPORARY TABLE ", stderr);
00995 ut_print_name(stderr, NULL, TRUE, old_name);
00996 fputs(" (", stderr);
00997 ut_print_filename(stderr,
00998 table->dir_path_of_temp_table);
00999 fputs(" )\n", stderr);
01000 return(FALSE);
01001 } else if (!fil_rename_tablespace(old_name, table->space,
01002 new_name)) {
01003 return(FALSE);
01004 }
01005 }
01006
01007
01008 HASH_DELETE(dict_table_t, name_hash, dict_sys->table_hash,
01009 ut_fold_string(old_name), table);
01010
01011 if (strlen(new_name) > strlen(table->name)) {
01012
01013
01014
01015 ut_a(strlen(new_name) <= MAX_TABLE_NAME_LEN);
01016 table->name = static_cast<char *>(ut_realloc(table->name, MAX_TABLE_NAME_LEN + 1));
01017 }
01018 memcpy(table->name, new_name, strlen(new_name) + 1);
01019
01020
01021 HASH_INSERT(dict_table_t, name_hash, dict_sys->table_hash, fold,
01022 table);
01023
01024 dict_sys->size += strlen(new_name) - strlen(old_name);
01025 ut_a(dict_sys->size > 0);
01026
01027
01028 index = dict_table_get_first_index(table);
01029
01030 while (index != NULL) {
01031 index->table_name = table->name;
01032
01033 index = dict_table_get_next_index(index);
01034 }
01035
01036 if (!rename_also_foreigns) {
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046 foreign = UT_LIST_GET_LAST(table->foreign_list);
01047
01048 while (foreign != NULL) {
01049 dict_foreign_remove_from_cache(foreign);
01050 foreign = UT_LIST_GET_LAST(table->foreign_list);
01051 }
01052
01053
01054
01055 foreign = UT_LIST_GET_FIRST(table->referenced_list);
01056
01057 while (foreign != NULL) {
01058 foreign->referenced_table = NULL;
01059 foreign->referenced_index = NULL;
01060
01061 foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
01062 }
01063
01064
01065
01066 UT_LIST_INIT(table->referenced_list);
01067
01068 return(TRUE);
01069 }
01070
01071
01072
01073
01074
01075 foreign = UT_LIST_GET_FIRST(table->foreign_list);
01076
01077 while (foreign != NULL) {
01078 if (ut_strlen(foreign->foreign_table_name)
01079 < ut_strlen(table->name)) {
01080
01081
01082
01083 foreign->foreign_table_name
01084 = static_cast<char *>(mem_heap_alloc(foreign->heap,
01085 ut_strlen(table->name) + 1));
01086 }
01087
01088 strcpy(foreign->foreign_table_name, table->name);
01089
01090 if (strchr(foreign->id, '/')) {
01091 ulint db_len;
01092 char* old_id;
01093
01094
01095
01096 old_id = mem_strdup(foreign->id);
01097
01098 if (ut_strlen(foreign->id) > ut_strlen(old_name)
01099 + ((sizeof dict_ibfk) - 1)
01100 && !memcmp(foreign->id, old_name,
01101 ut_strlen(old_name))
01102 && !memcmp(foreign->id + ut_strlen(old_name),
01103 dict_ibfk, (sizeof dict_ibfk) - 1)) {
01104
01105
01106
01107 if (strlen(table->name) > strlen(old_name)) {
01108 foreign->id = static_cast<char *>(mem_heap_alloc(
01109 foreign->heap,
01110 strlen(table->name)
01111 + strlen(old_id) + 1));
01112 }
01113
01114
01115
01116 strcpy(foreign->id, table->name);
01117 strcat(foreign->id,
01118 old_id + ut_strlen(old_name));
01119 } else {
01120
01121
01122 db_len = dict_get_db_name_len(table->name) + 1;
01123
01124 if (dict_get_db_name_len(table->name)
01125 > dict_get_db_name_len(foreign->id)) {
01126
01127 foreign->id = static_cast<char *>(mem_heap_alloc(
01128 foreign->heap,
01129 db_len + strlen(old_id) + 1));
01130 }
01131
01132
01133
01134
01135 ut_memcpy(foreign->id, table->name, db_len);
01136
01137 strcpy(foreign->id + db_len,
01138 dict_remove_db_name(old_id));
01139 }
01140
01141 mem_free(old_id);
01142 }
01143
01144 foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
01145 }
01146
01147 foreign = UT_LIST_GET_FIRST(table->referenced_list);
01148
01149 while (foreign != NULL) {
01150 if (ut_strlen(foreign->referenced_table_name)
01151 < ut_strlen(table->name)) {
01152
01153
01154
01155 foreign->referenced_table_name = static_cast<char *>(mem_heap_alloc(
01156 foreign->heap, strlen(table->name) + 1));
01157 }
01158
01159 strcpy(foreign->referenced_table_name, table->name);
01160
01161 foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
01162 }
01163
01164 return(TRUE);
01165 }
01166
01167
01170 UNIV_INTERN
01171 void
01172 dict_table_change_id_in_cache(
01173
01174 dict_table_t* table,
01175 table_id_t new_id)
01176 {
01177 ut_ad(table);
01178 ut_ad(mutex_own(&(dict_sys->mutex)));
01179 ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
01180
01181
01182
01183 HASH_DELETE(dict_table_t, id_hash, dict_sys->table_id_hash,
01184 ut_fold_ull(table->id), table);
01185 table->id = new_id;
01186
01187
01188 HASH_INSERT(dict_table_t, id_hash, dict_sys->table_id_hash,
01189 ut_fold_ull(table->id), table);
01190 }
01191
01192
01194 UNIV_INTERN
01195 void
01196 dict_table_remove_from_cache(
01197
01198 dict_table_t* table)
01199 {
01200 dict_foreign_t* foreign;
01201 dict_index_t* index;
01202 ulint size;
01203
01204 ut_ad(table);
01205 ut_ad(mutex_own(&(dict_sys->mutex)));
01206 ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
01207
01208 #if 0
01209 fputs("Removing table ", stderr);
01210 ut_print_name(stderr, table->name, ULINT_UNDEFINED);
01211 fputs(" from dictionary cache\n", stderr);
01212 #endif
01213
01214
01215 foreign = UT_LIST_GET_LAST(table->foreign_list);
01216
01217 while (foreign != NULL) {
01218 dict_foreign_remove_from_cache(foreign);
01219 foreign = UT_LIST_GET_LAST(table->foreign_list);
01220 }
01221
01222
01223
01224 foreign = UT_LIST_GET_FIRST(table->referenced_list);
01225
01226 while (foreign != NULL) {
01227 foreign->referenced_table = NULL;
01228 foreign->referenced_index = NULL;
01229
01230 foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
01231 }
01232
01233
01234 index = UT_LIST_GET_LAST(table->indexes);
01235
01236 while (index != NULL) {
01237 dict_index_remove_from_cache(table, index);
01238 index = UT_LIST_GET_LAST(table->indexes);
01239 }
01240
01241
01242 HASH_DELETE(dict_table_t, name_hash, dict_sys->table_hash,
01243 ut_fold_string(table->name), table);
01244 HASH_DELETE(dict_table_t, id_hash, dict_sys->table_id_hash,
01245 ut_fold_ull(table->id), table);
01246
01247
01248 UT_LIST_REMOVE(table_LRU, dict_sys->table_LRU, table);
01249
01250 size = mem_heap_get_size(table->heap) + strlen(table->name) + 1;
01251
01252 ut_ad(dict_sys->size >= size);
01253
01254 dict_sys->size -= size;
01255
01256 dict_mem_table_free(table);
01257 }
01258
01259
01263 UNIV_INTERN
01264 ibool
01265 dict_col_name_is_reserved(
01266
01267 const char* name)
01268 {
01269
01270
01271 #if DATA_N_SYS_COLS != 3
01272 #error "DATA_N_SYS_COLS != 3"
01273 #endif
01274
01275 static const char* reserved_names[] = {
01276 "DB_ROW_ID", "DB_TRX_ID", "DB_ROLL_PTR"
01277 };
01278
01279 ulint i;
01280
01281 for (i = 0; i < UT_ARR_SIZE(reserved_names); i++) {
01282 if (innobase_strcasecmp(name, reserved_names[i]) == 0) {
01283
01284 return(TRUE);
01285 }
01286 }
01287
01288 return(FALSE);
01289 }
01290
01291
01295 static
01296 ibool
01297 dict_index_too_big_for_undo(
01298
01299 const dict_table_t* table,
01300 const dict_index_t* new_index)
01301 {
01302
01303
01304
01305 ulint i;
01306 const dict_index_t* clust_index
01307 = dict_table_get_first_index(table);
01308 ulint undo_page_len
01309 = TRX_UNDO_PAGE_HDR - TRX_UNDO_PAGE_HDR_SIZE
01310 + 2
01311 + 1
01312 + 11 + 11
01313 + 1
01314 + 11
01315 + 11
01316 + 10 + FIL_PAGE_DATA_END
01317 + 2;
01318
01319 if (UNIV_UNLIKELY(!clust_index)) {
01320 ut_a(dict_index_is_clust(new_index));
01321 clust_index = new_index;
01322 }
01323
01324
01325
01326 for (i = 0; i < clust_index->n_uniq; i++) {
01327 const dict_col_t* col
01328 = dict_index_get_nth_col(clust_index, i);
01329
01330
01331
01332
01333 undo_page_len += 5 + dict_col_get_max_size(col);
01334 }
01335
01336
01337
01338
01339
01340
01341
01342 undo_page_len += 2 * (dict_table_get_n_cols(table) + 1);
01343
01344 for (i = 0; i < clust_index->n_def; i++) {
01345 const dict_col_t* col
01346 = dict_index_get_nth_col(clust_index, i);
01347 ulint max_size
01348 = dict_col_get_max_size(col);
01349 ulint fixed_size
01350 = dict_col_get_fixed_size(col,
01351 dict_table_is_comp(table));
01352
01353 if (fixed_size) {
01354
01355 max_size = fixed_size;
01356 } else if (max_size <= BTR_EXTERN_FIELD_REF_SIZE * 2) {
01357
01358 } else if (!col->ord_part) {
01359
01360
01361 ulint j;
01362
01363 for (j = 0; j < new_index->n_uniq; j++) {
01364 if (dict_index_get_nth_col(
01365 new_index, j) == col) {
01366
01367 goto is_ord_part;
01368 }
01369 }
01370
01371
01372
01373 max_size = BTR_EXTERN_FIELD_REF_SIZE;
01374 } else {
01375 is_ord_part:
01376
01377
01378
01379
01380 if (max_size > REC_MAX_INDEX_COL_LEN) {
01381 max_size = REC_MAX_INDEX_COL_LEN;
01382 }
01383
01384 max_size += BTR_EXTERN_FIELD_REF_SIZE;
01385 }
01386
01387 undo_page_len += 5 + max_size;
01388 }
01389
01390 return(undo_page_len >= UNIV_PAGE_SIZE);
01391 }
01392
01393
01397 static
01398 ibool
01399 dict_index_too_big_for_tree(
01400
01401 const dict_table_t* table,
01402 const dict_index_t* new_index)
01403 {
01404 ulint zip_size;
01405 ulint comp;
01406 ulint i;
01407
01408 ulint rec_max_size;
01409
01410 ulint page_rec_max;
01411
01412 ulint page_ptr_max;
01413
01414 comp = dict_table_is_comp(table);
01415 zip_size = dict_table_zip_size(table);
01416
01417 if (zip_size && zip_size < UNIV_PAGE_SIZE) {
01418
01419
01420
01421
01422 ut_ad(comp);
01423
01424
01425
01426
01427 page_rec_max = page_zip_empty_size(new_index->n_fields,
01428 zip_size) - 1;
01429 page_ptr_max = page_rec_max / 2;
01430
01431
01432
01433 rec_max_size = 2;
01434 } else {
01435
01436
01437
01438 page_rec_max = page_get_free_space_of_empty(comp) / 2;
01439 page_ptr_max = page_rec_max;
01440
01441 rec_max_size = comp
01442 ? REC_N_NEW_EXTRA_BYTES
01443 : REC_N_OLD_EXTRA_BYTES;
01444 }
01445
01446 if (comp) {
01447
01448
01449 rec_max_size += UT_BITS_IN_BYTES(new_index->n_nullable);
01450 } else {
01451
01452
01453
01454
01455
01456 rec_max_size += 2 * new_index->n_fields;
01457 }
01458
01459
01460 for (i = 0; i < new_index->n_fields; i++) {
01461 const dict_field_t* field
01462 = dict_index_get_nth_field(new_index, i);
01463 const dict_col_t* col
01464 = dict_field_get_col(field);
01465 ulint field_max_size;
01466 ulint field_ext_max_size;
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480 field_max_size = dict_col_get_fixed_size(col, comp);
01481 if (field_max_size) {
01482
01483 ut_ad(!field->prefix_len
01484 || field->fixed_len == field->prefix_len);
01485
01486
01487 field_ext_max_size = 0;
01488 goto add_field_size;
01489 }
01490
01491 field_max_size = dict_col_get_max_size(col);
01492 field_ext_max_size = field_max_size < 256 ? 1 : 2;
01493
01494 if (field->prefix_len) {
01495 if (field->prefix_len < field_max_size) {
01496 field_max_size = field->prefix_len;
01497 }
01498 } else if (field_max_size > BTR_EXTERN_FIELD_REF_SIZE * 2
01499 && dict_index_is_clust(new_index)) {
01500
01501
01502
01503
01504
01505
01506
01507 field_max_size = BTR_EXTERN_FIELD_REF_SIZE * 2;
01508 field_ext_max_size = 1;
01509 }
01510
01511 if (comp) {
01512
01513
01514
01515 rec_max_size += field_ext_max_size;
01516 }
01517 add_field_size:
01518 rec_max_size += field_max_size;
01519
01520
01521 if (UNIV_UNLIKELY(rec_max_size >= page_rec_max)) {
01522
01523 return(TRUE);
01524 }
01525
01526
01527
01528
01529
01530
01531
01532 if (i + 1 == dict_index_get_n_unique_in_tree(new_index)
01533 && rec_max_size + REC_NODE_PTR_SIZE >= page_ptr_max) {
01534
01535 return(TRUE);
01536 }
01537 }
01538
01539 return(FALSE);
01540 }
01541
01542
01545 UNIV_INTERN
01546 ulint
01547 dict_index_add_to_cache(
01548
01549 dict_table_t* table,
01550 dict_index_t* index,
01552 ulint page_no,
01553 ibool strict)
01556 {
01557 dict_index_t* new_index;
01558 ulint n_ord;
01559 ulint i;
01560
01561 ut_ad(index);
01562 ut_ad(mutex_own(&(dict_sys->mutex)));
01563 ut_ad(index->n_def == index->n_fields);
01564 ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
01565
01566 ut_ad(mem_heap_validate(index->heap));
01567 ut_a(!dict_index_is_clust(index)
01568 || UT_LIST_GET_LEN(table->indexes) == 0);
01569
01570 if (!dict_index_find_cols(table, index)) {
01571
01572 dict_mem_index_free(index);
01573 return(DB_CORRUPTION);
01574 }
01575
01576
01577
01578
01579 if (dict_index_is_clust(index)) {
01580 new_index = dict_index_build_internal_clust(table, index);
01581 } else {
01582 new_index = dict_index_build_internal_non_clust(table, index);
01583 }
01584
01585
01586
01587
01588 new_index->n_fields = new_index->n_def;
01589
01590 if (strict && dict_index_too_big_for_tree(table, new_index)) {
01591 too_big:
01592 dict_mem_index_free(new_index);
01593 dict_mem_index_free(index);
01594 return(DB_TOO_BIG_RECORD);
01595 }
01596
01597 if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
01598 n_ord = new_index->n_fields;
01599 } else {
01600 n_ord = new_index->n_uniq;
01601 }
01602
01603 switch (dict_table_get_format(table)) {
01604 case DICT_TF_FORMAT_51:
01605
01606
01607
01608
01609 goto undo_size_ok;
01610
01611 case DICT_TF_FORMAT_ZIP:
01612
01613
01614
01615
01616
01617
01618
01619 break;
01620
01621 #if DICT_TF_FORMAT_ZIP != DICT_TF_FORMAT_MAX
01622 # error "DICT_TF_FORMAT_ZIP != DICT_TF_FORMAT_MAX"
01623 #endif
01624 }
01625
01626 for (i = 0; i < n_ord; i++) {
01627 const dict_field_t* field
01628 = dict_index_get_nth_field(new_index, i);
01629 const dict_col_t* col
01630 = dict_field_get_col(field);
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642 if (field->prefix_len
01643 && !col->ord_part
01644 && !dict_col_get_fixed_size(col, TRUE)
01645 && dict_col_get_max_size(col)
01646 > BTR_EXTERN_FIELD_REF_SIZE * 2 ) {
01647
01648 if (dict_index_too_big_for_undo(table, new_index)) {
01649
01650
01651
01652 goto too_big;
01653 }
01654
01655 break;
01656 }
01657 }
01658
01659 undo_size_ok:
01660
01661
01662 for (i = 0; i < n_ord; i++) {
01663
01664 dict_index_get_nth_field(new_index, i)->col->ord_part = 1;
01665 }
01666
01667
01668
01669 UT_LIST_ADD_LAST(indexes, table->indexes, new_index);
01670 new_index->table = table;
01671 new_index->table_name = table->name;
01672
01673 new_index->search_info = btr_search_info_create(new_index->heap);
01674
01675 new_index->stat_index_size = 1;
01676 new_index->stat_n_leaf_pages = 1;
01677
01678 new_index->page = page_no;
01679 rw_lock_create(index_tree_rw_lock_key, &new_index->lock,
01680 SYNC_INDEX_TREE);
01681
01682 if (!UNIV_UNLIKELY(new_index->type & DICT_UNIVERSAL)) {
01683
01684 new_index->stat_n_diff_key_vals = static_cast<ib_int64_t *>(mem_heap_alloc(
01685 new_index->heap,
01686 (1 + dict_index_get_n_unique(new_index))
01687 * sizeof(ib_int64_t)));
01688
01689
01690
01691 for (i = 0; i <= dict_index_get_n_unique(new_index); i++) {
01692
01693 new_index->stat_n_diff_key_vals[i] = 100;
01694 }
01695 }
01696
01697 dict_sys->size += mem_heap_get_size(new_index->heap);
01698
01699 dict_mem_index_free(index);
01700
01701 return(DB_SUCCESS);
01702 }
01703
01704
01706 UNIV_INTERN
01707 void
01708 dict_index_remove_from_cache(
01709
01710 dict_table_t* table,
01711 dict_index_t* index)
01712 {
01713 ulint size;
01714 ulint retries = 0;
01715 btr_search_t* info;
01716
01717 ut_ad(table && index);
01718 ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
01719 ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
01720 ut_ad(mutex_own(&(dict_sys->mutex)));
01721
01722
01723
01724 info = index->search_info;
01725 ut_ad(info);
01726
01727
01728
01729
01730
01731
01732
01733
01734
01735
01736 for (;;) {
01737 ulint ref_count = btr_search_info_get_ref_count(info);
01738 if (ref_count == 0) {
01739 break;
01740 }
01741
01742
01743 os_thread_sleep(10000);
01744 ++retries;
01745
01746 if (retries % 500 == 0) {
01747
01748 fprintf(stderr, "InnoDB: Error: Waited for"
01749 " %lu secs for hash index"
01750 " ref_count (%lu) to drop"
01751 " to 0.\n"
01752 "index: \"%s\""
01753 " table: \"%s\"\n",
01754 retries/100,
01755 ref_count,
01756 index->name,
01757 table->name);
01758 }
01759
01760
01761
01762 if (retries >= 60000) {
01763 ut_error;
01764 }
01765 }
01766
01767 rw_lock_free(&index->lock);
01768
01769
01770 UT_LIST_REMOVE(indexes, table->indexes, index);
01771
01772 size = mem_heap_get_size(index->heap);
01773
01774 ut_ad(dict_sys->size >= size);
01775
01776 dict_sys->size -= size;
01777
01778 dict_mem_index_free(index);
01779 }
01780
01781
01785 static
01786 ibool
01787 dict_index_find_cols(
01788
01789 dict_table_t* table,
01790 dict_index_t* index)
01791 {
01792 ulint i;
01793
01794 ut_ad(table && index);
01795 ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
01796 ut_ad(mutex_own(&(dict_sys->mutex)));
01797
01798 for (i = 0; i < index->n_fields; i++) {
01799 ulint j;
01800 dict_field_t* field = dict_index_get_nth_field(index, i);
01801
01802 for (j = 0; j < table->n_cols; j++) {
01803 if (!strcmp(dict_table_get_col_name(table, j),
01804 field->name)) {
01805 field->col = dict_table_get_nth_col(table, j);
01806
01807 goto found;
01808 }
01809 }
01810
01811 #ifdef UNIV_DEBUG
01812
01813 fputs("InnoDB: Error: no matching column for ", stderr);
01814 ut_print_name(stderr, NULL, FALSE, field->name);
01815 fputs(" in ", stderr);
01816 dict_index_name_print(stderr, NULL, index);
01817 fputs("!\n", stderr);
01818 #endif
01819 return(FALSE);
01820
01821 found:
01822 ;
01823 }
01824
01825 return(TRUE);
01826 }
01827 #endif
01828
01829
01831 UNIV_INTERN
01832 void
01833 dict_index_add_col(
01834
01835 dict_index_t* index,
01836 const dict_table_t* table,
01837 dict_col_t* col,
01838 ulint prefix_len)
01839 {
01840 dict_field_t* field;
01841 const char* col_name;
01842
01843 col_name = dict_table_get_col_name(table, dict_col_get_no(col));
01844
01845 dict_mem_index_add_field(index, col_name, prefix_len);
01846
01847 field = dict_index_get_nth_field(index, index->n_def - 1);
01848
01849 field->col = col;
01850 field->fixed_len = (unsigned int) dict_col_get_fixed_size(
01851 col, dict_table_is_comp(table));
01852
01853 if (prefix_len && field->fixed_len > prefix_len) {
01854 field->fixed_len = (unsigned int) prefix_len;
01855 }
01856
01857
01858
01859
01860
01861 if (field->fixed_len > DICT_MAX_INDEX_COL_LEN) {
01862 field->fixed_len = 0;
01863 }
01864 #if DICT_MAX_INDEX_COL_LEN != 1024
01865
01866
01867
01868 # error "DICT_MAX_INDEX_COL_LEN != 1024"
01869 #endif
01870
01871 if (!(col->prtype & DATA_NOT_NULL)) {
01872 index->n_nullable++;
01873 }
01874 }
01875
01876 #ifndef UNIV_HOTBACKUP
01877
01879 static
01880 void
01881 dict_index_copy(
01882
01883 dict_index_t* index1,
01884 dict_index_t* index2,
01885 const dict_table_t* table,
01886 ulint start,
01887 ulint end)
01888 {
01889 dict_field_t* field;
01890 ulint i;
01891
01892
01893
01894 for (i = start; i < end; i++) {
01895
01896 field = dict_index_get_nth_field(index2, i);
01897 dict_index_add_col(index1, table, field->col,
01898 field->prefix_len);
01899 }
01900 }
01901
01902
01904 UNIV_INTERN
01905 void
01906 dict_index_copy_types(
01907
01908 dtuple_t* tuple,
01909 const dict_index_t* index,
01910 ulint n_fields)
01912 {
01913 ulint i;
01914
01915 if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
01916 dtuple_set_types_binary(tuple, n_fields);
01917
01918 return;
01919 }
01920
01921 for (i = 0; i < n_fields; i++) {
01922 const dict_field_t* ifield;
01923 dtype_t* dfield_type;
01924
01925 ifield = dict_index_get_nth_field(index, i);
01926 dfield_type = dfield_get_type(dtuple_get_nth_field(tuple, i));
01927 dict_col_copy_type(dict_field_get_col(ifield), dfield_type);
01928 }
01929 }
01930
01931
01935 UNIV_INTERN
01936 void
01937 dict_table_copy_types(
01938
01939 dtuple_t* tuple,
01940 const dict_table_t* table)
01941 {
01942 ulint i;
01943
01944 for (i = 0; i < dtuple_get_n_fields(tuple); i++) {
01945
01946 dfield_t* dfield = dtuple_get_nth_field(tuple, i);
01947 dtype_t* dtype = dfield_get_type(dfield);
01948
01949 dfield_set_null(dfield);
01950 dict_col_copy_type(dict_table_get_nth_col(table, i), dtype);
01951 }
01952 }
01953
01954
01958 static
01959 dict_index_t*
01960 dict_index_build_internal_clust(
01961
01962 const dict_table_t* table,
01963 dict_index_t* index)
01965 {
01966 dict_index_t* new_index;
01967 dict_field_t* field;
01968 ulint fixed_size;
01969 ulint trx_id_pos;
01970 ulint i;
01971 ibool* indexed;
01972
01973 ut_ad(table && index);
01974 ut_ad(dict_index_is_clust(index));
01975 ut_ad(mutex_own(&(dict_sys->mutex)));
01976 ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
01977
01978
01979 new_index = dict_mem_index_create(table->name,
01980 index->name, table->space,
01981 index->type,
01982 index->n_fields + table->n_cols);
01983
01984
01985
01986
01987 new_index->n_user_defined_cols = index->n_fields;
01988
01989 new_index->id = index->id;
01990
01991
01992 dict_index_copy(new_index, index, table, 0, index->n_fields);
01993
01994 if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
01995
01996
01997 new_index->n_uniq = REC_MAX_N_FIELDS;
01998
01999 } else if (dict_index_is_unique(index)) {
02000
02001
02002
02003 new_index->n_uniq = new_index->n_def;
02004 } else {
02005
02006 new_index->n_uniq = 1 + new_index->n_def;
02007 }
02008
02009 new_index->trx_id_offset = 0;
02010
02011 if (!dict_index_is_ibuf(index)) {
02012
02013
02014 trx_id_pos = new_index->n_def;
02015
02016 #if DATA_ROW_ID != 0
02017 # error "DATA_ROW_ID != 0"
02018 #endif
02019 #if DATA_TRX_ID != 1
02020 # error "DATA_TRX_ID != 1"
02021 #endif
02022 #if DATA_ROLL_PTR != 2
02023 # error "DATA_ROLL_PTR != 2"
02024 #endif
02025
02026 if (!dict_index_is_unique(index)) {
02027 dict_index_add_col(new_index, table,
02028 dict_table_get_sys_col(
02029 table, DATA_ROW_ID),
02030 0);
02031 trx_id_pos++;
02032 }
02033
02034 dict_index_add_col(new_index, table,
02035 dict_table_get_sys_col(table, DATA_TRX_ID),
02036 0);
02037
02038 dict_index_add_col(new_index, table,
02039 dict_table_get_sys_col(table,
02040 DATA_ROLL_PTR),
02041 0);
02042
02043 for (i = 0; i < trx_id_pos; i++) {
02044
02045 fixed_size = dict_col_get_fixed_size(
02046 dict_index_get_nth_col(new_index, i),
02047 dict_table_is_comp(table));
02048
02049 if (fixed_size == 0) {
02050 new_index->trx_id_offset = 0;
02051
02052 break;
02053 }
02054
02055 if (dict_index_get_nth_field(new_index, i)->prefix_len
02056 > 0) {
02057 new_index->trx_id_offset = 0;
02058
02059 break;
02060 }
02061
02062 new_index->trx_id_offset += (unsigned int) fixed_size;
02063 }
02064
02065 }
02066
02067
02068 void *indexed_ptr= mem_zalloc(table->n_cols * sizeof *indexed);
02069 indexed = static_cast<unsigned long *>(indexed_ptr);
02070
02071
02072 for (i = 0; i < new_index->n_def; i++) {
02073
02074 field = dict_index_get_nth_field(new_index, i);
02075
02076
02077
02078
02079 if (field->prefix_len == 0) {
02080
02081 indexed[field->col->ind] = TRUE;
02082 }
02083 }
02084
02085
02086
02087 for (i = 0; i + DATA_N_SYS_COLS < (ulint) table->n_cols; i++) {
02088
02089 dict_col_t* col = dict_table_get_nth_col(table, i);
02090 ut_ad(col->mtype != DATA_SYS);
02091
02092 if (!indexed[col->ind]) {
02093 dict_index_add_col(new_index, table, col, 0);
02094 }
02095 }
02096
02097 mem_free(indexed);
02098
02099 ut_ad(dict_index_is_ibuf(index)
02100 || (UT_LIST_GET_LEN(table->indexes) == 0));
02101
02102 new_index->cached = TRUE;
02103
02104 return(new_index);
02105 }
02106
02107
02111 static
02112 dict_index_t*
02113 dict_index_build_internal_non_clust(
02114
02115 const dict_table_t* table,
02116 dict_index_t* index)
02118 {
02119 dict_field_t* field;
02120 dict_index_t* new_index;
02121 dict_index_t* clust_index;
02122 ulint i;
02123 ibool* indexed;
02124
02125 ut_ad(table && index);
02126 ut_ad(!dict_index_is_clust(index));
02127 ut_ad(mutex_own(&(dict_sys->mutex)));
02128 ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
02129
02130
02131 clust_index = UT_LIST_GET_FIRST(table->indexes);
02132
02133 ut_ad(clust_index);
02134 ut_ad(dict_index_is_clust(clust_index));
02135 ut_ad(!(clust_index->type & DICT_UNIVERSAL));
02136
02137
02138 new_index = dict_mem_index_create(
02139 table->name, index->name, index->space, index->type,
02140 index->n_fields + 1 + clust_index->n_uniq);
02141
02142
02143
02144
02145 new_index->n_user_defined_cols = index->n_fields;
02146
02147 new_index->id = index->id;
02148
02149
02150 dict_index_copy(new_index, index, table, 0, index->n_fields);
02151
02152
02153 void *indexed_ptr= mem_zalloc(table->n_cols * sizeof *indexed);
02154 indexed = static_cast<unsigned long *>(indexed_ptr);
02155
02156
02157 for (i = 0; i < new_index->n_def; i++) {
02158
02159 field = dict_index_get_nth_field(new_index, i);
02160
02161
02162
02163
02164 if (field->prefix_len == 0) {
02165
02166 indexed[field->col->ind] = TRUE;
02167 }
02168 }
02169
02170
02171
02172
02173 for (i = 0; i < clust_index->n_uniq; i++) {
02174
02175 field = dict_index_get_nth_field(clust_index, i);
02176
02177 if (!indexed[field->col->ind]) {
02178 dict_index_add_col(new_index, table, field->col,
02179 field->prefix_len);
02180 }
02181 }
02182
02183 mem_free(indexed);
02184
02185 if (dict_index_is_unique(index)) {
02186 new_index->n_uniq = index->n_fields;
02187 } else {
02188 new_index->n_uniq = new_index->n_def;
02189 }
02190
02191
02192
02193
02194 new_index->n_fields = new_index->n_def;
02195
02196 new_index->cached = TRUE;
02197
02198 return(new_index);
02199 }
02200
02201
02202
02203
02206 UNIV_INTERN
02207 ibool
02208 dict_table_is_referenced_by_foreign_key(
02209
02210 const dict_table_t* table)
02211 {
02212 return(UT_LIST_GET_LEN(table->referenced_list) > 0);
02213 }
02214
02215
02220 UNIV_INTERN
02221 dict_foreign_t*
02222 dict_table_get_referenced_constraint(
02223
02224 dict_table_t* table,
02225 dict_index_t* index)
02226 {
02227 dict_foreign_t* foreign;
02228
02229 ut_ad(index != NULL);
02230 ut_ad(table != NULL);
02231
02232 for (foreign = UT_LIST_GET_FIRST(table->referenced_list);
02233 foreign;
02234 foreign = UT_LIST_GET_NEXT(referenced_list, foreign)) {
02235
02236 if (foreign->referenced_index == index) {
02237
02238 return(foreign);
02239 }
02240 }
02241
02242 return(NULL);
02243 }
02244
02245
02251 UNIV_INTERN
02252 dict_foreign_t*
02253 dict_table_get_foreign_constraint(
02254
02255 dict_table_t* table,
02256 dict_index_t* index)
02257 {
02258 dict_foreign_t* foreign;
02259
02260 ut_ad(index != NULL);
02261 ut_ad(table != NULL);
02262
02263 for (foreign = UT_LIST_GET_FIRST(table->foreign_list);
02264 foreign;
02265 foreign = UT_LIST_GET_NEXT(foreign_list, foreign)) {
02266
02267 if (foreign->foreign_index == index
02268 || foreign->referenced_index == index) {
02269
02270 return(foreign);
02271 }
02272 }
02273
02274 return(NULL);
02275 }
02276
02277
02279 static
02280 void
02281 dict_foreign_free(
02282
02283 dict_foreign_t* foreign)
02284 {
02285 mem_heap_free(foreign->heap);
02286 }
02287
02288
02290 static
02291 void
02292 dict_foreign_remove_from_cache(
02293
02294 dict_foreign_t* foreign)
02295 {
02296 ut_ad(mutex_own(&(dict_sys->mutex)));
02297 ut_a(foreign);
02298
02299 if (foreign->referenced_table) {
02300 UT_LIST_REMOVE(referenced_list,
02301 foreign->referenced_table->referenced_list,
02302 foreign);
02303 }
02304
02305 if (foreign->foreign_table) {
02306 UT_LIST_REMOVE(foreign_list,
02307 foreign->foreign_table->foreign_list,
02308 foreign);
02309 }
02310
02311 dict_foreign_free(foreign);
02312 }
02313
02314
02318 static
02319 dict_foreign_t*
02320 dict_foreign_find(
02321
02322 dict_table_t* table,
02323 const char* id)
02324 {
02325 dict_foreign_t* foreign;
02326
02327 ut_ad(mutex_own(&(dict_sys->mutex)));
02328
02329 foreign = UT_LIST_GET_FIRST(table->foreign_list);
02330
02331 while (foreign) {
02332 if (ut_strcmp(id, foreign->id) == 0) {
02333
02334 return(foreign);
02335 }
02336
02337 foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
02338 }
02339
02340 foreign = UT_LIST_GET_FIRST(table->referenced_list);
02341
02342 while (foreign) {
02343 if (ut_strcmp(id, foreign->id) == 0) {
02344
02345 return(foreign);
02346 }
02347
02348 foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
02349 }
02350
02351 return(NULL);
02352 }
02353
02354
02359 static
02360 dict_index_t*
02361 dict_foreign_find_index(
02362
02363 dict_table_t* table,
02364 const char** columns,
02365 ulint n_cols,
02366 dict_index_t* types_idx,
02368 ibool check_charsets,
02371 ulint check_null)
02374 {
02375 dict_index_t* index;
02376
02377 index = dict_table_get_first_index(table);
02378
02379 while (index != NULL) {
02380
02381
02382 if (index->to_be_dropped || types_idx == index) {
02383
02384 goto next_rec;
02385
02386 } else if (dict_index_get_n_fields(index) >= n_cols) {
02387 ulint i;
02388
02389 for (i = 0; i < n_cols; i++) {
02390 dict_field_t* field;
02391 const char* col_name;
02392
02393 field = dict_index_get_nth_field(index, i);
02394
02395 col_name = dict_table_get_col_name(
02396 table, dict_col_get_no(field->col));
02397
02398 if (field->prefix_len != 0) {
02399
02400
02401
02402 break;
02403 }
02404
02405 if (0 != innobase_strcasecmp(columns[i],
02406 col_name)) {
02407 break;
02408 }
02409
02410 if (check_null
02411 && (field->col->prtype & DATA_NOT_NULL)) {
02412
02413 return(NULL);
02414 }
02415
02416 if (types_idx && !cmp_cols_are_equal(
02417 dict_index_get_nth_col(index, i),
02418 dict_index_get_nth_col(types_idx,
02419 i),
02420 check_charsets)) {
02421
02422 break;
02423 }
02424 }
02425
02426 if (i == n_cols) {
02427
02428
02429 return(index);
02430 }
02431 }
02432
02433 next_rec:
02434 index = dict_table_get_next_index(index);
02435 }
02436
02437 return(NULL);
02438 }
02439
02440
02444 UNIV_INTERN
02445 dict_index_t*
02446 dict_foreign_find_equiv_index(
02447
02448 dict_foreign_t* foreign)
02449 {
02450 ut_a(foreign != NULL);
02451
02452
02453
02454
02455
02456 return(dict_foreign_find_index(
02457 foreign->foreign_table,
02458 foreign->foreign_col_names, foreign->n_fields,
02459 foreign->foreign_index, TRUE,
02460 FALSE));
02461 }
02462
02463
02467 UNIV_INTERN
02468 dict_index_t*
02469 dict_table_get_index_by_max_id(
02470
02471 dict_table_t* table,
02472 const char* name,
02473 const char** columns,
02474 ulint n_cols)
02475 {
02476 dict_index_t* index;
02477 dict_index_t* found;
02478
02479 found = NULL;
02480 index = dict_table_get_first_index(table);
02481
02482 while (index != NULL) {
02483 if (ut_strcmp(index->name, name) == 0
02484 && dict_index_get_n_ordering_defined_by_user(index)
02485 == n_cols) {
02486
02487 ulint i;
02488
02489 for (i = 0; i < n_cols; i++) {
02490 dict_field_t* field;
02491 const char* col_name;
02492
02493 field = dict_index_get_nth_field(index, i);
02494
02495 col_name = dict_table_get_col_name(
02496 table, dict_col_get_no(field->col));
02497
02498 if (0 != innobase_strcasecmp(
02499 columns[i], col_name)) {
02500
02501 break;
02502 }
02503 }
02504
02505 if (i == n_cols) {
02506
02507
02508
02509 if (!found || index->id > found->id) {
02510
02511 found = index;
02512 }
02513 }
02514 }
02515
02516 index = dict_table_get_next_index(index);
02517 }
02518
02519 return(found);
02520 }
02521
02522
02524 static
02525 void
02526 dict_foreign_error_report_low(
02527
02528 FILE* file,
02529 const char* name)
02530 {
02531 rewind(file);
02532 ut_print_timestamp(file);
02533 fprintf(file, " Error in foreign key constraint of table %s:\n",
02534 name);
02535 }
02536
02537
02539 static
02540 void
02541 dict_foreign_error_report(
02542
02543 FILE* file,
02544 dict_foreign_t* fk,
02545 const char* msg)
02546 {
02547 mutex_enter(&dict_foreign_err_mutex);
02548 dict_foreign_error_report_low(file, fk->foreign_table_name);
02549 fputs(msg, file);
02550 fputs(" Constraint:\n", file);
02551 dict_print_info_on_foreign_key_in_create_format(file, NULL, fk, TRUE);
02552 putc('\n', file);
02553 if (fk->foreign_index) {
02554 fputs("The index in the foreign key in table is ", file);
02555 ut_print_name(file, NULL, FALSE, fk->foreign_index->name);
02556 fputs("\n"
02557 "See " REFMAN "innodb-foreign-key-constraints.html\n"
02558 "for correct foreign key definition.\n",
02559 file);
02560 }
02561 mutex_exit(&dict_foreign_err_mutex);
02562 }
02563
02564
02570 UNIV_INTERN
02571 ulint
02572 dict_foreign_add_to_cache(
02573
02574 dict_foreign_t* foreign,
02575 ibool check_charsets)
02577 {
02578 dict_table_t* for_table;
02579 dict_table_t* ref_table;
02580 dict_foreign_t* for_in_cache = NULL;
02581 dict_index_t* index;
02582 ibool added_to_referenced_list= FALSE;
02583 FILE* ef = dict_foreign_err_file;
02584
02585 ut_ad(mutex_own(&(dict_sys->mutex)));
02586
02587 for_table = dict_table_check_if_in_cache_low(
02588 foreign->foreign_table_name);
02589
02590 ref_table = dict_table_check_if_in_cache_low(
02591 foreign->referenced_table_name);
02592 ut_a(for_table || ref_table);
02593
02594 if (for_table) {
02595 for_in_cache = dict_foreign_find(for_table, foreign->id);
02596 }
02597
02598 if (!for_in_cache && ref_table) {
02599 for_in_cache = dict_foreign_find(ref_table, foreign->id);
02600 }
02601
02602 if (for_in_cache) {
02603
02604 mem_heap_free(foreign->heap);
02605 } else {
02606 for_in_cache = foreign;
02607 }
02608
02609 if (for_in_cache->referenced_table == NULL && ref_table) {
02610 index = dict_foreign_find_index(
02611 ref_table,
02612 for_in_cache->referenced_col_names,
02613 for_in_cache->n_fields, for_in_cache->foreign_index,
02614 check_charsets, FALSE);
02615
02616 if (index == NULL) {
02617 dict_foreign_error_report(
02618 ef, for_in_cache,
02619 "there is no index in referenced table"
02620 " which would contain\n"
02621 "the columns as the first columns,"
02622 " or the data types in the\n"
02623 "referenced table do not match"
02624 " the ones in table.");
02625
02626 if (for_in_cache == foreign) {
02627 mem_heap_free(foreign->heap);
02628 }
02629
02630 return(DB_CANNOT_ADD_CONSTRAINT);
02631 }
02632
02633 for_in_cache->referenced_table = ref_table;
02634 for_in_cache->referenced_index = index;
02635 UT_LIST_ADD_LAST(referenced_list,
02636 ref_table->referenced_list,
02637 for_in_cache);
02638 added_to_referenced_list = TRUE;
02639 }
02640
02641 if (for_in_cache->foreign_table == NULL && for_table) {
02642 index = dict_foreign_find_index(
02643 for_table,
02644 for_in_cache->foreign_col_names,
02645 for_in_cache->n_fields,
02646 for_in_cache->referenced_index, check_charsets,
02647 for_in_cache->type
02648 & (DICT_FOREIGN_ON_DELETE_SET_NULL
02649 | DICT_FOREIGN_ON_UPDATE_SET_NULL));
02650
02651 if (index == NULL) {
02652 dict_foreign_error_report(
02653 ef, for_in_cache,
02654 "there is no index in the table"
02655 " which would contain\n"
02656 "the columns as the first columns,"
02657 " or the data types in the\n"
02658 "table do not match"
02659 " the ones in the referenced table\n"
02660 "or one of the ON ... SET NULL columns"
02661 " is declared NOT NULL.");
02662
02663 if (for_in_cache == foreign) {
02664 if (added_to_referenced_list) {
02665 UT_LIST_REMOVE(
02666 referenced_list,
02667 ref_table->referenced_list,
02668 for_in_cache);
02669 }
02670
02671 mem_heap_free(foreign->heap);
02672 }
02673
02674 return(DB_CANNOT_ADD_CONSTRAINT);
02675 }
02676
02677 for_in_cache->foreign_table = for_table;
02678 for_in_cache->foreign_index = index;
02679 UT_LIST_ADD_LAST(foreign_list,
02680 for_table->foreign_list,
02681 for_in_cache);
02682 }
02683
02684 return(DB_SUCCESS);
02685 }
02686
02687
02692 static
02693 const char*
02694 dict_scan_to(
02695
02696 const char* ptr,
02697 const char* string)
02698 {
02699 char quote = '\0';
02700
02701 for (; *ptr; ptr++) {
02702 if (*ptr == quote) {
02703
02704
02705 quote = '\0';
02706 } else if (quote) {
02707
02708 } else if (*ptr == '`' || *ptr == '"') {
02709
02710 quote = *ptr;
02711 } else {
02712
02713 ulint i;
02714 for (i = 0; string[i]; i++) {
02715 if (toupper((int)(unsigned char)(ptr[i]))
02716 != toupper((int)(unsigned char)
02717 (string[i]))) {
02718 goto nomatch;
02719 }
02720 }
02721 break;
02722 nomatch:
02723 ;
02724 }
02725 }
02726
02727 return(ptr);
02728 }
02729
02730
02734 static
02735 const char*
02736 dict_accept(
02737
02738 const void* cs,
02739 const char* ptr,
02740 const char* string,
02742 ibool* success)
02743 {
02744 const char* old_ptr = ptr;
02745 const char* old_ptr2;
02746
02747 *success = FALSE;
02748
02749 while (innobase_isspace(cs, *ptr)) {
02750 ptr++;
02751 }
02752
02753 old_ptr2 = ptr;
02754
02755 ptr = dict_scan_to(ptr, string);
02756
02757 if (*ptr == '\0' || old_ptr2 != ptr) {
02758 return(old_ptr);
02759 }
02760
02761 *success = TRUE;
02762
02763 return(ptr + ut_strlen(string));
02764 }
02765
02766
02770 static
02771 const char*
02772 dict_scan_id(
02773
02774 const void* cs,
02775 const char* ptr,
02776 mem_heap_t* heap,
02779 const char** id,
02781 ibool table_id,
02783 ibool accept_also_dot)
02787 {
02788 char quote = '\0';
02789 ulint len = 0;
02790 const char* s;
02791 char* str;
02792 char* dst;
02793
02794 *id = NULL;
02795
02796 while (innobase_isspace(cs, *ptr)) {
02797 ptr++;
02798 }
02799
02800 if (*ptr == '\0') {
02801
02802 return(ptr);
02803 }
02804
02805 if (*ptr == '`' || *ptr == '"') {
02806 quote = *ptr++;
02807 }
02808
02809 s = ptr;
02810
02811 if (quote) {
02812 for (;;) {
02813 if (!*ptr) {
02814
02815 return(ptr);
02816 }
02817 if (*ptr == quote) {
02818 ptr++;
02819 if (*ptr != quote) {
02820 break;
02821 }
02822 }
02823 ptr++;
02824 len++;
02825 }
02826 } else {
02827 while (!innobase_isspace(cs, *ptr) && *ptr != '(' && *ptr != ')'
02828 && (accept_also_dot || *ptr != '.')
02829 && *ptr != ',' && *ptr != '\0') {
02830
02831 ptr++;
02832 }
02833
02834 len = ptr - s;
02835 }
02836
02837 if (UNIV_UNLIKELY(!heap)) {
02838
02839 *id = s;
02840 return(ptr);
02841 }
02842
02843 if (quote) {
02844 char* d;
02845 str = d = static_cast<char *>(mem_heap_alloc(heap, len + 1));
02846 while (len--) {
02847 if ((*d++ = *s++) == quote) {
02848 s++;
02849 }
02850 }
02851 *d++ = 0;
02852 len = d - str;
02853 ut_ad(*s == quote);
02854 ut_ad(s + 1 == ptr);
02855 } else {
02856 str = mem_heap_strdupl(heap, s, len);
02857 }
02858
02859 if (!table_id) {
02860 convert_id:
02861
02862
02863 len = 3 * len + 1;
02864 *id = dst = static_cast<char *>(mem_heap_alloc(heap, len));
02865
02866 innobase_convert_from_id(cs, dst, str, len);
02867 } else if (!strncmp(str, srv_mysql50_table_name_prefix.c_str(),
02868 srv_mysql50_table_name_prefix.size())) {
02869
02870
02871
02872 str += srv_mysql50_table_name_prefix.size();
02873 len -= srv_mysql50_table_name_prefix.size();
02874 goto convert_id;
02875 } else {
02876
02877 len = 5 * len + 1;
02878 *id = dst = static_cast<char *>(mem_heap_alloc(heap, len));
02879
02880 innobase_convert_from_table_id(cs, dst, str, len);
02881 }
02882
02883 return(ptr);
02884 }
02885
02886
02889 static
02890 const char*
02891 dict_scan_col(
02892
02893 const void* cs,
02894 const char* ptr,
02895 ibool* success,
02896 dict_table_t* table,
02897 const dict_col_t** column,
02898 mem_heap_t* heap,
02899 const char** name)
02901 {
02902 ulint i;
02903
02904 *success = FALSE;
02905
02906 ptr = dict_scan_id(cs, ptr, heap, name, FALSE, TRUE);
02907
02908 if (*name == NULL) {
02909
02910 return(ptr);
02911 }
02912
02913 if (table == NULL) {
02914 *success = TRUE;
02915 *column = NULL;
02916 } else {
02917 for (i = 0; i < dict_table_get_n_cols(table); i++) {
02918
02919 const char* col_name = dict_table_get_col_name(
02920 table, i);
02921
02922 if (0 == innobase_strcasecmp(col_name, *name)) {
02923
02924
02925 *success = TRUE;
02926 *column = dict_table_get_nth_col(table, i);
02927 strcpy((char*) *name, col_name);
02928
02929 break;
02930 }
02931 }
02932 }
02933
02934 return(ptr);
02935 }
02936
02937
02940 static
02941 const char*
02942 dict_scan_table_name(
02943
02944 const void* cs,
02945 const char* ptr,
02946 dict_table_t** table,
02947 const char* name,
02948 ibool* success,
02949 mem_heap_t* heap,
02950 const char** ref_name)
02952 {
02953 const char* database_name = NULL;
02954 ulint database_name_len = 0;
02955 const char* table_name = NULL;
02956 ulint table_name_len;
02957 const char* scan_name;
02958 char* ref;
02959
02960 *success = FALSE;
02961 *table = NULL;
02962
02963 ptr = dict_scan_id(cs, ptr, heap, &scan_name, TRUE, FALSE);
02964
02965 if (scan_name == NULL) {
02966
02967 return(ptr);
02968 }
02969
02970 if (*ptr == '.') {
02971
02972
02973 ptr++;
02974
02975 database_name = scan_name;
02976 database_name_len = strlen(database_name);
02977
02978 ptr = dict_scan_id(cs, ptr, heap, &table_name, TRUE, FALSE);
02979
02980 if (table_name == NULL) {
02981
02982 return(ptr);
02983 }
02984 } else {
02985
02986
02987
02988
02989
02990
02991
02992 const char* s;
02993
02994 for (s = scan_name; *s; s++) {
02995 if (*s == '.') {
02996 database_name = scan_name;
02997 database_name_len = s - scan_name;
02998 scan_name = ++s;
02999 break;
03000 }
03001 }
03002
03003 table_name = scan_name;
03004 }
03005
03006 if (database_name == NULL) {
03007
03008
03009 database_name = name;
03010 database_name_len = dict_get_db_name_len(name);
03011 }
03012
03013 table_name_len = strlen(table_name);
03014
03015
03016 ref = static_cast<char *>(mem_heap_alloc(heap, database_name_len + table_name_len + 2));
03017 memcpy(ref, database_name, database_name_len);
03018 ref[database_name_len] = '/';
03019 memcpy(ref + database_name_len + 1, table_name, table_name_len + 1);
03020 #ifndef __WIN__
03021 if (srv_lower_case_table_names) {
03022 #endif
03023
03024 innobase_casedn_str(ref);
03025 #ifndef __WIN__
03026 }
03027 #endif
03028
03029 *success = TRUE;
03030 *ref_name = ref;
03031 *table = dict_table_get_low(ref);
03032
03033 return(ptr);
03034 }
03035
03036
03039 static
03040 const char*
03041 dict_skip_word(
03042
03043 const void* cs,
03044 const char* ptr,
03045 ibool* success)
03047 {
03048 const char* start;
03049
03050 *success = FALSE;
03051
03052 ptr = dict_scan_id(cs, ptr, NULL, &start, FALSE, TRUE);
03053
03054 if (start) {
03055 *success = TRUE;
03056 }
03057
03058 return(ptr);
03059 }
03060
03061
03069 static
03070 char*
03071 dict_strip_comments(
03072
03073 const char* sql_string,
03074 size_t sql_length)
03075 {
03076 char* str;
03077 const char* sptr;
03078 const char* eptr = sql_string + sql_length;
03079 char* ptr;
03080
03081 char quote = 0;
03082
03083 str = static_cast<char *>(mem_alloc(sql_length + 1));
03084
03085 sptr = sql_string;
03086 ptr = str;
03087
03088 for (;;) {
03089 scan_more:
03090 if (sptr >= eptr || *sptr == '\0') {
03091 end_of_string:
03092 *ptr = '\0';
03093
03094 ut_a(ptr <= str + sql_length);
03095
03096 return(str);
03097 }
03098
03099 if (*sptr == quote) {
03100
03101
03102 quote = 0;
03103 } else if (quote) {
03104
03105
03106 } else if (*sptr == '"' || *sptr == '`' || *sptr == '\'') {
03107
03108 quote = *sptr;
03109 } else if (*sptr == '#'
03110 || (sptr[0] == '-' && sptr[1] == '-'
03111 && sptr[2] == ' ')) {
03112 for (;;) {
03113 if (++sptr >= eptr) {
03114 goto end_of_string;
03115 }
03116
03117
03118
03119
03120 switch (*sptr) {
03121 case (char) 0X0A:
03122 case (char) 0x0D:
03123 case '\0':
03124 goto scan_more;
03125 }
03126 }
03127 } else if (!quote && *sptr == '/' && *(sptr + 1) == '*') {
03128 sptr += 2;
03129 for (;;) {
03130 if (sptr >= eptr) {
03131 goto end_of_string;
03132 }
03133
03134 switch (*sptr) {
03135 case '\0':
03136 goto scan_more;
03137 case '*':
03138 if (sptr[1] == '/') {
03139 sptr += 2;
03140 goto scan_more;
03141 }
03142 }
03143
03144 sptr++;
03145 }
03146 }
03147
03148 *ptr = *sptr;
03149
03150 ptr++;
03151 sptr++;
03152 }
03153 }
03154
03155
03160 static
03161 ulint
03162 dict_table_get_highest_foreign_id(
03163
03164 dict_table_t* table)
03165 {
03166 dict_foreign_t* foreign;
03167 char* endp;
03168 ulint biggest_id = 0;
03169 ulint id;
03170 ulint len;
03171
03172 ut_a(table);
03173
03174 len = ut_strlen(table->name);
03175 foreign = UT_LIST_GET_FIRST(table->foreign_list);
03176
03177 while (foreign) {
03178 if (ut_strlen(foreign->id) > ((sizeof dict_ibfk) - 1) + len
03179 && 0 == ut_memcmp(foreign->id, table->name, len)
03180 && 0 == ut_memcmp(foreign->id + len,
03181 dict_ibfk, (sizeof dict_ibfk) - 1)
03182 && foreign->id[len + ((sizeof dict_ibfk) - 1)] != '0') {
03183
03184
03185 id = strtoul(foreign->id + len
03186 + ((sizeof dict_ibfk) - 1),
03187 &endp, 10);
03188 if (*endp == '\0') {
03189 ut_a(id != biggest_id);
03190
03191 if (id > biggest_id) {
03192 biggest_id = id;
03193 }
03194 }
03195 }
03196
03197 foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
03198 }
03199
03200 return(biggest_id);
03201 }
03202
03203
03205 static
03206 void
03207 dict_foreign_report_syntax_err(
03208
03209 const char* name,
03210 const char* start_of_latest_foreign,
03213 const char* ptr)
03214 {
03215 FILE* ef = dict_foreign_err_file;
03216
03217 mutex_enter(&dict_foreign_err_mutex);
03218 dict_foreign_error_report_low(ef, name);
03219 fprintf(ef, "%s:\nSyntax error close to:\n%s\n",
03220 start_of_latest_foreign, ptr);
03221 mutex_exit(&dict_foreign_err_mutex);
03222 }
03223
03224
03231 static
03232 ulint
03233 dict_create_foreign_constraints_low(
03234
03235 trx_t* trx,
03236 mem_heap_t* heap,
03237 const void* cs,
03238 const char* sql_string,
03245 const char* name,
03247 ibool reject_fks)
03251 {
03252 dict_table_t* table;
03253 dict_table_t* referenced_table;
03254 dict_table_t* table_to_alter;
03255 ulint highest_id_so_far = 0;
03256 dict_index_t* index;
03257 dict_foreign_t* foreign;
03258 const char* ptr = sql_string;
03259 const char* start_of_latest_foreign = sql_string;
03260 FILE* ef = dict_foreign_err_file;
03261 const char* constraint_name;
03262 ibool success;
03263 ulint error;
03264 const char* ptr1;
03265 const char* ptr2;
03266 ulint i;
03267 ulint j;
03268 ibool is_on_delete;
03269 ulint n_on_deletes;
03270 ulint n_on_updates;
03271 const dict_col_t*columns[500];
03272 const char* column_names[500];
03273 const char* referenced_table_name;
03274
03275 ut_ad(mutex_own(&(dict_sys->mutex)));
03276
03277 table = dict_table_get_low(name);
03278
03279 if (table == NULL) {
03280 mutex_enter(&dict_foreign_err_mutex);
03281 dict_foreign_error_report_low(ef, name);
03282 fprintf(ef,
03283 "Cannot find the table in the internal"
03284 " data dictionary of InnoDB.\n"
03285 "Create table statement:\n%s\n", sql_string);
03286 mutex_exit(&dict_foreign_err_mutex);
03287
03288 return(DB_ERROR);
03289 }
03290
03291
03292
03293
03294 ptr = dict_accept(cs, ptr, "ALTER", &success);
03295
03296 if (!success) {
03297
03298 goto loop;
03299 }
03300
03301 ptr = dict_accept(cs, ptr, "TABLE", &success);
03302
03303 if (!success) {
03304
03305 goto loop;
03306 }
03307
03308
03309
03310 ptr = dict_scan_table_name(cs, ptr, &table_to_alter, name,
03311 &success, heap, &referenced_table_name);
03312 if (!success) {
03313 fprintf(stderr,
03314 "InnoDB: Error: could not find"
03315 " the table being ALTERED in:\n%s\n",
03316 sql_string);
03317
03318 return(DB_ERROR);
03319 }
03320
03321
03322
03323
03324
03325
03326
03327
03328
03329
03330 if (table_to_alter == NULL) {
03331 highest_id_so_far = 0;
03332 } else {
03333 highest_id_so_far = dict_table_get_highest_foreign_id(
03334 table_to_alter);
03335 }
03336
03337
03338 loop:
03339
03340
03341 ptr1 = dict_scan_to(ptr, "CONSTRAINT");
03342 ptr2 = dict_scan_to(ptr, "FOREIGN");
03343
03344 constraint_name = NULL;
03345
03346 if (ptr1 < ptr2) {
03347
03348
03349
03350 ptr = ptr1;
03351
03352 ptr = dict_accept(cs, ptr, "CONSTRAINT", &success);
03353
03354 ut_a(success);
03355
03356 if (!innobase_isspace(cs, *ptr) && *ptr != '"' && *ptr != '`') {
03357 goto loop;
03358 }
03359
03360 while (innobase_isspace(cs, *ptr)) {
03361 ptr++;
03362 }
03363
03364
03365 if (ptr != ptr2) {
03366 ptr = dict_scan_id(cs, ptr, heap,
03367 &constraint_name, FALSE, FALSE);
03368 }
03369 } else {
03370 ptr = ptr2;
03371 }
03372
03373 if (*ptr == '\0') {
03374
03375
03376
03377
03378
03379
03380
03381 if (reject_fks && (UT_LIST_GET_LEN(table->foreign_list) > 0)) {
03382
03383 return(DB_CANNOT_ADD_CONSTRAINT);
03384 }
03385
03386
03387
03388
03389
03390 error = dict_create_add_foreigns_to_dictionary(
03391 highest_id_so_far, table, trx);
03392 return(error);
03393 }
03394
03395 start_of_latest_foreign = ptr;
03396
03397 ptr = dict_accept(cs, ptr, "FOREIGN", &success);
03398
03399 if (!success) {
03400 goto loop;
03401 }
03402
03403 if (!innobase_isspace(cs, *ptr)) {
03404 goto loop;
03405 }
03406
03407 ptr = dict_accept(cs, ptr, "KEY", &success);
03408
03409 if (!success) {
03410 goto loop;
03411 }
03412
03413 ptr = dict_accept(cs, ptr, "(", &success);
03414
03415 if (!success) {
03416
03417
03418 ptr = dict_skip_word(cs, ptr, &success);
03419
03420 if (!success) {
03421 dict_foreign_report_syntax_err(
03422 name, start_of_latest_foreign, ptr);
03423
03424 return(DB_CANNOT_ADD_CONSTRAINT);
03425 }
03426
03427 ptr = dict_accept(cs, ptr, "(", &success);
03428
03429 if (!success) {
03430
03431
03432
03433 goto loop;
03434 }
03435 }
03436
03437 i = 0;
03438
03439
03440 col_loop1:
03441 ut_a(i < (sizeof column_names) / sizeof *column_names);
03442 ptr = dict_scan_col(cs, ptr, &success, table, columns + i,
03443 heap, column_names + i);
03444 if (!success) {
03445 mutex_enter(&dict_foreign_err_mutex);
03446 dict_foreign_error_report_low(ef, name);
03447 fprintf(ef, "%s:\nCannot resolve column name close to:\n%s\n",
03448 start_of_latest_foreign, ptr);
03449 mutex_exit(&dict_foreign_err_mutex);
03450
03451 return(DB_CANNOT_ADD_CONSTRAINT);
03452 }
03453
03454 i++;
03455
03456 ptr = dict_accept(cs, ptr, ",", &success);
03457
03458 if (success) {
03459 goto col_loop1;
03460 }
03461
03462 ptr = dict_accept(cs, ptr, ")", &success);
03463
03464 if (!success) {
03465 dict_foreign_report_syntax_err(
03466 name, start_of_latest_foreign, ptr);
03467 return(DB_CANNOT_ADD_CONSTRAINT);
03468 }
03469
03470
03471
03472
03473 index = dict_foreign_find_index(table, column_names, i,
03474 NULL, TRUE, FALSE);
03475
03476 if (!index) {
03477 mutex_enter(&dict_foreign_err_mutex);
03478 dict_foreign_error_report_low(ef, name);
03479 fputs("There is no index in table ", ef);
03480 ut_print_name(ef, NULL, TRUE, name);
03481 fprintf(ef, " where the columns appear\n"
03482 "as the first columns. Constraint:\n%s\n"
03483 "See " REFMAN "innodb-foreign-key-constraints.html\n"
03484 "for correct foreign key definition.\n",
03485 start_of_latest_foreign);
03486 mutex_exit(&dict_foreign_err_mutex);
03487
03488 return(DB_CHILD_NO_INDEX);
03489 }
03490 ptr = dict_accept(cs, ptr, "REFERENCES", &success);
03491
03492 if (!success || !innobase_isspace(cs, *ptr)) {
03493 dict_foreign_report_syntax_err(
03494 name, start_of_latest_foreign, ptr);
03495 return(DB_CANNOT_ADD_CONSTRAINT);
03496 }
03497
03498
03499
03500 foreign = dict_mem_foreign_create();
03501
03502 if (constraint_name) {
03503 ulint db_len;
03504
03505
03506
03507
03508
03509
03510 db_len = dict_get_db_name_len(table->name);
03511
03512 foreign->id = static_cast<char*>(mem_heap_alloc(
03513 foreign->heap, db_len + strlen(constraint_name) + 2));
03514
03515 ut_memcpy(foreign->id, table->name, db_len);
03516 foreign->id[db_len] = '/';
03517 strcpy(foreign->id + db_len + 1, constraint_name);
03518 }
03519
03520 foreign->foreign_table = table;
03521 foreign->foreign_table_name = mem_heap_strdup(foreign->heap,
03522 table->name);
03523 foreign->foreign_index = index;
03524 foreign->n_fields = (unsigned int) i;
03525 foreign->foreign_col_names = static_cast<const char **>(mem_heap_alloc(foreign->heap,
03526 i * sizeof(void*)));
03527 for (i = 0; i < foreign->n_fields; i++) {
03528 foreign->foreign_col_names[i] = mem_heap_strdup(
03529 foreign->heap,
03530 dict_table_get_col_name(table,
03531 dict_col_get_no(columns[i])));
03532 }
03533
03534 ptr = dict_scan_table_name(cs, ptr, &referenced_table, name,
03535 &success, heap, &referenced_table_name);
03536
03537
03538
03539
03540 if (!success || (!referenced_table && trx->check_foreigns)) {
03541 dict_foreign_free(foreign);
03542
03543 mutex_enter(&dict_foreign_err_mutex);
03544 dict_foreign_error_report_low(ef, name);
03545 fprintf(ef, "%s:\nCannot resolve table name close to:\n"
03546 "%s\n",
03547 start_of_latest_foreign, ptr);
03548 mutex_exit(&dict_foreign_err_mutex);
03549
03550 return(DB_CANNOT_ADD_CONSTRAINT);
03551 }
03552
03553 ptr = dict_accept(cs, ptr, "(", &success);
03554
03555 if (!success) {
03556 dict_foreign_free(foreign);
03557 dict_foreign_report_syntax_err(name, start_of_latest_foreign,
03558 ptr);
03559 return(DB_CANNOT_ADD_CONSTRAINT);
03560 }
03561
03562
03563 i = 0;
03564
03565 col_loop2:
03566 ptr = dict_scan_col(cs, ptr, &success, referenced_table, columns + i,
03567 heap, column_names + i);
03568 i++;
03569
03570 if (!success) {
03571 dict_foreign_free(foreign);
03572
03573 mutex_enter(&dict_foreign_err_mutex);
03574 dict_foreign_error_report_low(ef, name);
03575 fprintf(ef, "%s:\nCannot resolve column name close to:\n"
03576 "%s\n",
03577 start_of_latest_foreign, ptr);
03578 mutex_exit(&dict_foreign_err_mutex);
03579
03580 return(DB_CANNOT_ADD_CONSTRAINT);
03581 }
03582
03583 ptr = dict_accept(cs, ptr, ",", &success);
03584
03585 if (success) {
03586 goto col_loop2;
03587 }
03588
03589 ptr = dict_accept(cs, ptr, ")", &success);
03590
03591 if (!success || foreign->n_fields != i) {
03592 dict_foreign_free(foreign);
03593
03594 dict_foreign_report_syntax_err(name, start_of_latest_foreign,
03595 ptr);
03596 return(DB_CANNOT_ADD_CONSTRAINT);
03597 }
03598
03599 n_on_deletes = 0;
03600 n_on_updates = 0;
03601
03602 scan_on_conditions:
03603
03604
03605 ptr = dict_accept(cs, ptr, "ON", &success);
03606
03607 if (!success) {
03608
03609 goto try_find_index;
03610 }
03611
03612 ptr = dict_accept(cs, ptr, "DELETE", &success);
03613
03614 if (!success) {
03615 ptr = dict_accept(cs, ptr, "UPDATE", &success);
03616
03617 if (!success) {
03618 dict_foreign_free(foreign);
03619
03620 dict_foreign_report_syntax_err(
03621 name, start_of_latest_foreign, ptr);
03622 return(DB_CANNOT_ADD_CONSTRAINT);
03623 }
03624
03625 is_on_delete = FALSE;
03626 n_on_updates++;
03627 } else {
03628 is_on_delete = TRUE;
03629 n_on_deletes++;
03630 }
03631
03632 ptr = dict_accept(cs, ptr, "RESTRICT", &success);
03633
03634 if (success) {
03635 goto scan_on_conditions;
03636 }
03637
03638 ptr = dict_accept(cs, ptr, "CASCADE", &success);
03639
03640 if (success) {
03641 if (is_on_delete) {
03642 foreign->type |= DICT_FOREIGN_ON_DELETE_CASCADE;
03643 } else {
03644 foreign->type |= DICT_FOREIGN_ON_UPDATE_CASCADE;
03645 }
03646
03647 goto scan_on_conditions;
03648 }
03649
03650 ptr = dict_accept(cs, ptr, "NO", &success);
03651
03652 if (success) {
03653 ptr = dict_accept(cs, ptr, "ACTION", &success);
03654
03655 if (!success) {
03656 dict_foreign_free(foreign);
03657 dict_foreign_report_syntax_err(
03658 name, start_of_latest_foreign, ptr);
03659
03660 return(DB_CANNOT_ADD_CONSTRAINT);
03661 }
03662
03663 if (is_on_delete) {
03664 foreign->type |= DICT_FOREIGN_ON_DELETE_NO_ACTION;
03665 } else {
03666 foreign->type |= DICT_FOREIGN_ON_UPDATE_NO_ACTION;
03667 }
03668
03669 goto scan_on_conditions;
03670 }
03671
03672 ptr = dict_accept(cs, ptr, "SET", &success);
03673
03674 if (!success) {
03675 dict_foreign_free(foreign);
03676 dict_foreign_report_syntax_err(name, start_of_latest_foreign,
03677 ptr);
03678 return(DB_CANNOT_ADD_CONSTRAINT);
03679 }
03680
03681 ptr = dict_accept(cs, ptr, "NULL", &success);
03682
03683 if (!success) {
03684 dict_foreign_free(foreign);
03685 dict_foreign_report_syntax_err(name, start_of_latest_foreign,
03686 ptr);
03687 return(DB_CANNOT_ADD_CONSTRAINT);
03688 }
03689
03690 for (j = 0; j < foreign->n_fields; j++) {
03691 if ((dict_index_get_nth_col(foreign->foreign_index, j)->prtype)
03692 & DATA_NOT_NULL) {
03693
03694
03695
03696
03697 dict_foreign_free(foreign);
03698
03699 mutex_enter(&dict_foreign_err_mutex);
03700 dict_foreign_error_report_low(ef, name);
03701 fprintf(ef, "%s:\n"
03702 "You have defined a SET NULL condition"
03703 " though some of the\n"
03704 "columns are defined as NOT NULL.\n",
03705 start_of_latest_foreign);
03706 mutex_exit(&dict_foreign_err_mutex);
03707
03708 return(DB_CANNOT_ADD_CONSTRAINT);
03709 }
03710 }
03711
03712 if (is_on_delete) {
03713 foreign->type |= DICT_FOREIGN_ON_DELETE_SET_NULL;
03714 } else {
03715 foreign->type |= DICT_FOREIGN_ON_UPDATE_SET_NULL;
03716 }
03717
03718 goto scan_on_conditions;
03719
03720 try_find_index:
03721 if (n_on_deletes > 1 || n_on_updates > 1) {
03722
03723
03724 dict_foreign_free(foreign);
03725
03726 mutex_enter(&dict_foreign_err_mutex);
03727 dict_foreign_error_report_low(ef, name);
03728 fprintf(ef, "%s:\n"
03729 "You have twice an ON DELETE clause"
03730 " or twice an ON UPDATE clause.\n",
03731 start_of_latest_foreign);
03732 mutex_exit(&dict_foreign_err_mutex);
03733
03734 return(DB_CANNOT_ADD_CONSTRAINT);
03735 }
03736
03737
03738
03739
03740
03741 if (referenced_table) {
03742 index = dict_foreign_find_index(referenced_table,
03743 column_names, i,
03744 foreign->foreign_index,
03745 TRUE, FALSE);
03746 if (!index) {
03747 dict_foreign_free(foreign);
03748 mutex_enter(&dict_foreign_err_mutex);
03749 dict_foreign_error_report_low(ef, name);
03750 fprintf(ef, "%s:\n"
03751 "Cannot find an index in the"
03752 " referenced table where the\n"
03753 "referenced columns appear as the"
03754 " first columns, or column types\n"
03755 "in the table and the referenced table"
03756 " do not match for constraint.\n"
03757 "Note that the internal storage type of"
03758 " ENUM and SET changed in\n"
03759 "tables created with >= InnoDB-4.1.12,"
03760 " and such columns in old tables\n"
03761 "cannot be referenced by such columns"
03762 " in new tables.\n"
03763 "See " REFMAN
03764 "innodb-foreign-key-constraints.html\n"
03765 "for correct foreign key definition.\n",
03766 start_of_latest_foreign);
03767 mutex_exit(&dict_foreign_err_mutex);
03768
03769 return(DB_PARENT_NO_INDEX);
03770 }
03771 } else {
03772 ut_a(trx->check_foreigns == FALSE);
03773 index = NULL;
03774 }
03775
03776 foreign->referenced_index = index;
03777 foreign->referenced_table = referenced_table;
03778
03779 foreign->referenced_table_name
03780 = mem_heap_strdup(foreign->heap, referenced_table_name);
03781
03782 foreign->referenced_col_names = static_cast<const char **>(mem_heap_alloc(foreign->heap,
03783 i * sizeof(void*)));
03784 for (i = 0; i < foreign->n_fields; i++) {
03785 foreign->referenced_col_names[i]
03786 = mem_heap_strdup(foreign->heap, column_names[i]);
03787 }
03788
03789
03790
03791 UT_LIST_ADD_LAST(foreign_list, table->foreign_list, foreign);
03792
03793 if (referenced_table) {
03794 UT_LIST_ADD_LAST(referenced_list,
03795 referenced_table->referenced_list,
03796 foreign);
03797 }
03798
03799 goto loop;
03800 }
03801
03802
03809 UNIV_INTERN
03810 ulint
03811 dict_create_foreign_constraints(
03812
03813 trx_t* trx,
03814 const char* sql_string,
03822 size_t sql_length,
03823 const char* name,
03826 ibool reject_fks)
03829 {
03830 char* str;
03831 ulint err;
03832 mem_heap_t* heap;
03833
03834 ut_a(trx);
03835 ut_a(trx->mysql_thd);
03836
03837 str = dict_strip_comments(sql_string, sql_length);
03838 heap = mem_heap_create(10000);
03839
03840 err = dict_create_foreign_constraints_low(
03841 trx, heap, trx->session()->charset(), str, name,
03842 reject_fks);
03843
03844 mem_heap_free(heap);
03845 mem_free(str);
03846
03847 return(err);
03848 }
03849
03850
03854 UNIV_INTERN
03855 ulint
03856 dict_foreign_parse_drop_constraints(
03857
03858 mem_heap_t* heap,
03860 trx_t* trx,
03861 dict_table_t* table,
03862 ulint* n,
03864 const char*** constraints_to_drop)
03866 {
03867 dict_foreign_t* foreign;
03868 ibool success;
03869 char* str;
03870 size_t len;
03871 const char* ptr;
03872 const char* id;
03873 FILE* ef = dict_foreign_err_file;
03874 const void* cs;
03875
03876 ut_a(trx);
03877 ut_a(trx->mysql_thd);
03878
03879 cs = trx->session()->charset();
03880
03881 *n = 0;
03882
03883 *constraints_to_drop = static_cast<const char **>(mem_heap_alloc(heap, 1000 * sizeof(char*)));
03884
03885 ptr= trx->session()->getQueryStringCopy(len);
03886
03887 str = dict_strip_comments(ptr, len);
03888
03889 ptr = str;
03890
03891 ut_ad(mutex_own(&(dict_sys->mutex)));
03892 loop:
03893 ptr = dict_scan_to(ptr, "DROP");
03894
03895 if (*ptr == '\0') {
03896 mem_free(str);
03897
03898 return(DB_SUCCESS);
03899 }
03900
03901 ptr = dict_accept(cs, ptr, "DROP", &success);
03902
03903 if (!innobase_isspace(cs, *ptr)) {
03904
03905 goto loop;
03906 }
03907
03908 ptr = dict_accept(cs, ptr, "FOREIGN", &success);
03909
03910 if (!success || !innobase_isspace(cs, *ptr)) {
03911
03912 goto loop;
03913 }
03914
03915 ptr = dict_accept(cs, ptr, "KEY", &success);
03916
03917 if (!success) {
03918
03919 goto syntax_error;
03920 }
03921
03922 ptr = dict_scan_id(cs, ptr, heap, &id, FALSE, TRUE);
03923
03924 if (id == NULL) {
03925
03926 goto syntax_error;
03927 }
03928
03929 ut_a(*n < 1000);
03930 (*constraints_to_drop)[*n] = id;
03931 (*n)++;
03932
03933
03934
03935 foreign = UT_LIST_GET_FIRST(table->foreign_list);
03936
03937 while (foreign != NULL) {
03938 if (0 == strcmp(foreign->id, id)
03939 || (strchr(foreign->id, '/')
03940 && 0 == strcmp(id,
03941 dict_remove_db_name(foreign->id)))) {
03942
03943 break;
03944 }
03945
03946 foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
03947 }
03948
03949 if (foreign == NULL) {
03950 mutex_enter(&dict_foreign_err_mutex);
03951 rewind(ef);
03952 ut_print_timestamp(ef);
03953 fputs(" Error in dropping of a foreign key constraint"
03954 " of table ", ef);
03955 ut_print_name(ef, NULL, TRUE, table->name);
03956 fputs(",\n"
03957 "in SQL command\n", ef);
03958 fputs(str, ef);
03959 fputs("\nCannot find a constraint with the given id ", ef);
03960 ut_print_name(ef, NULL, FALSE, id);
03961 fputs(".\n", ef);
03962 mutex_exit(&dict_foreign_err_mutex);
03963
03964 mem_free(str);
03965
03966 return(DB_CANNOT_DROP_CONSTRAINT);
03967 }
03968
03969 goto loop;
03970
03971 syntax_error:
03972 mutex_enter(&dict_foreign_err_mutex);
03973 rewind(ef);
03974 ut_print_timestamp(ef);
03975 fputs(" Syntax error in dropping of a"
03976 " foreign key constraint of table ", ef);
03977 ut_print_name(ef, NULL, TRUE, table->name);
03978 fprintf(ef, ",\n"
03979 "close to:\n%s\n in SQL command\n%s\n", ptr, str);
03980 mutex_exit(&dict_foreign_err_mutex);
03981
03982 mem_free(str);
03983
03984 return(DB_CANNOT_DROP_CONSTRAINT);
03985 }
03986
03987
03988
03989
03993 UNIV_INTERN
03994 dict_index_t*
03995 dict_index_get_if_in_cache_low(
03996
03997 index_id_t index_id)
03998 {
03999 ut_ad(mutex_own(&(dict_sys->mutex)));
04000
04001 return(dict_index_find_on_id_low(index_id));
04002 }
04003
04004 #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
04005
04008 UNIV_INTERN
04009 dict_index_t*
04010 dict_index_get_if_in_cache(
04011
04012 index_id_t index_id)
04013 {
04014 dict_index_t* index;
04015
04016 if (dict_sys == NULL) {
04017 return(NULL);
04018 }
04019
04020 mutex_enter(&(dict_sys->mutex));
04021
04022 index = dict_index_get_if_in_cache_low(index_id);
04023
04024 mutex_exit(&(dict_sys->mutex));
04025
04026 return(index);
04027 }
04028 #endif
04029
04030 #ifdef UNIV_DEBUG
04031
04035 UNIV_INTERN
04036 ibool
04037 dict_index_check_search_tuple(
04038
04039 const dict_index_t* index,
04040 const dtuple_t* tuple)
04041 {
04042 ut_a(index);
04043 ut_a(dtuple_get_n_fields_cmp(tuple)
04044 <= dict_index_get_n_unique_in_tree(index));
04045 return(TRUE);
04046 }
04047 #endif
04048
04049
04052 UNIV_INTERN
04053 dtuple_t*
04054 dict_index_build_node_ptr(
04055
04056 const dict_index_t* index,
04057 const rec_t* rec,
04059 ulint page_no,
04061 mem_heap_t* heap,
04063 ulint level)
04065 {
04066 dtuple_t* tuple;
04067 dfield_t* field;
04068 byte* buf;
04069 ulint n_unique;
04070
04071 if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
04072
04073
04074
04075
04076
04077 ut_a(!dict_table_is_comp(index->table));
04078 n_unique = rec_get_n_fields_old(rec);
04079
04080 if (level > 0) {
04081 ut_a(n_unique > 1);
04082 n_unique--;
04083 }
04084 } else {
04085 n_unique = dict_index_get_n_unique_in_tree(index);
04086 }
04087
04088 tuple = dtuple_create(heap, n_unique + 1);
04089
04090
04091
04092
04093
04094
04095
04096 dtuple_set_n_fields_cmp(tuple, n_unique);
04097
04098 dict_index_copy_types(tuple, index, n_unique);
04099
04100 buf = static_cast<unsigned char *>(mem_heap_alloc(heap, 4));
04101
04102 mach_write_to_4(buf, page_no);
04103
04104 field = dtuple_get_nth_field(tuple, n_unique);
04105 dfield_set_data(field, buf, 4);
04106
04107 dtype_set(dfield_get_type(field), DATA_SYS_CHILD, DATA_NOT_NULL, 4);
04108
04109 rec_copy_prefix_to_dtuple(tuple, rec, index, n_unique, heap);
04110 dtuple_set_info_bits(tuple, dtuple_get_info_bits(tuple)
04111 | REC_STATUS_NODE_PTR);
04112
04113 ut_ad(dtuple_check_typed(tuple));
04114
04115 return(tuple);
04116 }
04117
04118
04122 UNIV_INTERN
04123 rec_t*
04124 dict_index_copy_rec_order_prefix(
04125
04126 const dict_index_t* index,
04127 const rec_t* rec,
04129 ulint* n_fields,
04130 byte** buf,
04132 ulint* buf_size)
04133 {
04134 ulint n;
04135
04136 UNIV_PREFETCH_R(rec);
04137
04138 if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
04139 ut_a(!dict_table_is_comp(index->table));
04140 n = rec_get_n_fields_old(rec);
04141 } else {
04142 n = dict_index_get_n_unique_in_tree(index);
04143 }
04144
04145 *n_fields = n;
04146 return(rec_copy_prefix_to_buf(rec, index, n, buf, buf_size));
04147 }
04148
04149
04152 UNIV_INTERN
04153 dtuple_t*
04154 dict_index_build_data_tuple(
04155
04156 dict_index_t* index,
04157 rec_t* rec,
04158 ulint n_fields,
04159 mem_heap_t* heap)
04160 {
04161 dtuple_t* tuple;
04162
04163 ut_ad(dict_table_is_comp(index->table)
04164 || n_fields <= rec_get_n_fields_old(rec));
04165
04166 tuple = dtuple_create(heap, n_fields);
04167
04168 dict_index_copy_types(tuple, index, n_fields);
04169
04170 rec_copy_prefix_to_dtuple(tuple, rec, index, n_fields, heap);
04171
04172 ut_ad(dtuple_check_typed(tuple));
04173
04174 return(tuple);
04175 }
04176
04177
04179 UNIV_INTERN
04180 ulint
04181 dict_index_calc_min_rec_len(
04182
04183 const dict_index_t* index)
04184 {
04185 ulint sum = 0;
04186 ulint i;
04187 ulint comp = dict_table_is_comp(index->table);
04188
04189 if (comp) {
04190 ulint nullable = 0;
04191 sum = REC_N_NEW_EXTRA_BYTES;
04192 for (i = 0; i < dict_index_get_n_fields(index); i++) {
04193 const dict_col_t* col
04194 = dict_index_get_nth_col(index, i);
04195 ulint size = dict_col_get_fixed_size(col, comp);
04196 sum += size;
04197 if (!size) {
04198 size = col->len;
04199 sum += size < 128 ? 1 : 2;
04200 }
04201 if (!(col->prtype & DATA_NOT_NULL)) {
04202 nullable++;
04203 }
04204 }
04205
04206
04207 sum += UT_BITS_IN_BYTES(nullable);
04208
04209 return(sum);
04210 }
04211
04212 for (i = 0; i < dict_index_get_n_fields(index); i++) {
04213 sum += dict_col_get_fixed_size(
04214 dict_index_get_nth_col(index, i), comp);
04215 }
04216
04217 if (sum > 127) {
04218 sum += 2 * dict_index_get_n_fields(index);
04219 } else {
04220 sum += dict_index_get_n_fields(index);
04221 }
04222
04223 sum += REC_N_OLD_EXTRA_BYTES;
04224
04225 return(sum);
04226 }
04227
04228
04231 UNIV_INTERN
04232 void
04233 dict_update_statistics(
04234
04235 dict_table_t* table,
04236 ibool only_calc_if_missing_stats)
04240 {
04241 dict_index_t* index;
04242 ulint sum_of_index_sizes = 0;
04243
04244 if (table->ibd_file_missing) {
04245 ut_print_timestamp(stderr);
04246 fprintf(stderr,
04247 " InnoDB: cannot calculate statistics for table %s\n"
04248 "InnoDB: because the .ibd file is missing. For help,"
04249 " please refer to\n"
04250 "InnoDB: " REFMAN "innodb-troubleshooting.html\n",
04251 table->name);
04252
04253 return;
04254 }
04255
04256
04257
04258
04259 index = dict_table_get_first_index(table);
04260
04261 if (index == NULL) {
04262
04263
04264 return;
04265 }
04266
04267 dict_table_stats_lock(table, RW_X_LATCH);
04268
04269 if (only_calc_if_missing_stats && table->stat_initialized) {
04270 dict_table_stats_unlock(table, RW_X_LATCH);
04271 return;
04272 }
04273
04274 do {
04275 if (UNIV_LIKELY
04276 (srv_force_recovery < SRV_FORCE_NO_IBUF_MERGE
04277 || (srv_force_recovery < SRV_FORCE_NO_LOG_REDO
04278 && dict_index_is_clust(index)))) {
04279 ulint size;
04280 size = btr_get_size(index, BTR_TOTAL_SIZE);
04281
04282 index->stat_index_size = size;
04283
04284 sum_of_index_sizes += size;
04285
04286 size = btr_get_size(index, BTR_N_LEAF_PAGES);
04287
04288 if (size == 0) {
04289
04290 size = 1;
04291 }
04292
04293 index->stat_n_leaf_pages = size;
04294
04295 btr_estimate_number_of_different_key_vals(index);
04296 } else {
04297
04298
04299
04300
04301
04302
04303 ulint i;
04304
04305 sum_of_index_sizes++;
04306 index->stat_index_size = index->stat_n_leaf_pages = 1;
04307
04308 for (i = dict_index_get_n_unique(index); i; ) {
04309 index->stat_n_diff_key_vals[i--] = 1;
04310 }
04311 }
04312
04313 index = dict_table_get_next_index(index);
04314 } while (index);
04315
04316 index = dict_table_get_first_index(table);
04317
04318 table->stat_n_rows = index->stat_n_diff_key_vals[
04319 dict_index_get_n_unique(index)];
04320
04321 table->stat_clustered_index_size = index->stat_index_size;
04322
04323 table->stat_sum_of_other_index_sizes = sum_of_index_sizes
04324 - index->stat_index_size;
04325
04326 table->stat_initialized = TRUE;
04327
04328 table->stat_modified_counter = 0;
04329
04330 dict_table_stats_unlock(table, RW_X_LATCH);
04331 }
04332
04333
04335 static
04336 void
04337 dict_foreign_print_low(
04338
04339 dict_foreign_t* foreign)
04340 {
04341 ulint i;
04342
04343 ut_ad(mutex_own(&(dict_sys->mutex)));
04344
04345 fprintf(stderr, " FOREIGN KEY CONSTRAINT %s: %s (",
04346 foreign->id, foreign->foreign_table_name);
04347
04348 for (i = 0; i < foreign->n_fields; i++) {
04349 fprintf(stderr, " %s", foreign->foreign_col_names[i]);
04350 }
04351
04352 fprintf(stderr, " )\n"
04353 " REFERENCES %s (",
04354 foreign->referenced_table_name);
04355
04356 for (i = 0; i < foreign->n_fields; i++) {
04357 fprintf(stderr, " %s", foreign->referenced_col_names[i]);
04358 }
04359
04360 fputs(" )\n", stderr);
04361 }
04362
04363
04365 UNIV_INTERN
04366 void
04367 dict_table_print(
04368
04369 dict_table_t* table)
04370 {
04371 mutex_enter(&(dict_sys->mutex));
04372 dict_table_print_low(table);
04373 mutex_exit(&(dict_sys->mutex));
04374 }
04375
04376
04378 UNIV_INTERN
04379 void
04380 dict_table_print_by_name(
04381
04382 const char* name)
04383 {
04384 dict_table_t* table;
04385
04386 mutex_enter(&(dict_sys->mutex));
04387
04388 table = dict_table_get_low(name);
04389
04390 ut_a(table);
04391
04392 dict_table_print_low(table);
04393 mutex_exit(&(dict_sys->mutex));
04394 }
04395
04396
04398 UNIV_INTERN
04399 void
04400 dict_table_print_low(
04401
04402 dict_table_t* table)
04403 {
04404 dict_index_t* index;
04405 dict_foreign_t* foreign;
04406 ulint i;
04407
04408 ut_ad(mutex_own(&(dict_sys->mutex)));
04409
04410 dict_update_statistics(table, FALSE );
04411
04412 dict_table_stats_lock(table, RW_S_LATCH);
04413
04414 fprintf(stderr,
04415 "--------------------------------------\n"
04416 "TABLE: name %s, id %llu, flags %lx, columns %lu,"
04417 " indexes %lu, appr.rows %lu\n"
04418 " COLUMNS: ",
04419 table->name,
04420 (ullint) table->id,
04421 (ulong) table->flags,
04422 (ulong) table->n_cols,
04423 (ulong) UT_LIST_GET_LEN(table->indexes),
04424 (ulong) table->stat_n_rows);
04425
04426 for (i = 0; i < (ulint) table->n_cols; i++) {
04427 dict_col_print_low(table, dict_table_get_nth_col(table, i));
04428 fputs("; ", stderr);
04429 }
04430
04431 putc('\n', stderr);
04432
04433 index = UT_LIST_GET_FIRST(table->indexes);
04434
04435 while (index != NULL) {
04436 dict_index_print_low(index);
04437 index = UT_LIST_GET_NEXT(indexes, index);
04438 }
04439
04440 dict_table_stats_unlock(table, RW_S_LATCH);
04441
04442 foreign = UT_LIST_GET_FIRST(table->foreign_list);
04443
04444 while (foreign != NULL) {
04445 dict_foreign_print_low(foreign);
04446 foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
04447 }
04448
04449 foreign = UT_LIST_GET_FIRST(table->referenced_list);
04450
04451 while (foreign != NULL) {
04452 dict_foreign_print_low(foreign);
04453 foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
04454 }
04455 }
04456
04457
04459 static
04460 void
04461 dict_col_print_low(
04462
04463 const dict_table_t* table,
04464 const dict_col_t* col)
04465 {
04466 dtype_t type;
04467
04468 ut_ad(mutex_own(&(dict_sys->mutex)));
04469
04470 dict_col_copy_type(col, &type);
04471 fprintf(stderr, "%s: ", dict_table_get_col_name(table,
04472 dict_col_get_no(col)));
04473
04474 dtype_print(&type);
04475 }
04476
04477
04479 static
04480 void
04481 dict_index_print_low(
04482
04483 dict_index_t* index)
04484 {
04485 ib_int64_t n_vals;
04486 ulint i;
04487
04488 ut_ad(mutex_own(&(dict_sys->mutex)));
04489
04490 if (index->n_user_defined_cols > 0) {
04491 n_vals = index->stat_n_diff_key_vals[
04492 index->n_user_defined_cols];
04493 } else {
04494 n_vals = index->stat_n_diff_key_vals[1];
04495 }
04496
04497 fprintf(stderr,
04498 " INDEX: name %s, id %llu, fields %lu/%lu,"
04499 " uniq %lu, type %lu\n"
04500 " root page %lu, appr.key vals %lu,"
04501 " leaf pages %lu, size pages %lu\n"
04502 " FIELDS: ",
04503 index->name,
04504 (ullint) index->id,
04505 (ulong) index->n_user_defined_cols,
04506 (ulong) index->n_fields,
04507 (ulong) index->n_uniq,
04508 (ulong) index->type,
04509 (ulong) index->page,
04510 (ulong) n_vals,
04511 (ulong) index->stat_n_leaf_pages,
04512 (ulong) index->stat_index_size);
04513
04514 for (i = 0; i < index->n_fields; i++) {
04515 dict_field_print_low(dict_index_get_nth_field(index, i));
04516 }
04517
04518 putc('\n', stderr);
04519
04520 #ifdef UNIV_BTR_PRINT
04521 btr_print_size(index);
04522
04523 btr_print_index(index, 7);
04524 #endif
04525 }
04526
04527
04529 static
04530 void
04531 dict_field_print_low(
04532
04533 const dict_field_t* field)
04534 {
04535 ut_ad(mutex_own(&(dict_sys->mutex)));
04536
04537 fprintf(stderr, " %s", field->name);
04538
04539 if (field->prefix_len != 0) {
04540 fprintf(stderr, "(%lu)", (ulong) field->prefix_len);
04541 }
04542 }
04543
04544
04547 UNIV_INTERN
04548 void
04549 dict_print_info_on_foreign_key_in_create_format(
04550
04551 FILE* file,
04552 trx_t* trx,
04553 dict_foreign_t* foreign,
04554 ibool add_newline)
04555 {
04556 const char* stripped_id;
04557 ulint i;
04558
04559 if (strchr(foreign->id, '/')) {
04560
04561 stripped_id = foreign->id + 1
04562 + dict_get_db_name_len(foreign->id);
04563 } else {
04564 stripped_id = foreign->id;
04565 }
04566
04567 putc(',', file);
04568
04569 if (add_newline) {
04570
04571
04572
04573 fputs("\n ", file);
04574 }
04575
04576 fputs(" CONSTRAINT ", file);
04577 ut_print_name(file, trx, FALSE, stripped_id);
04578 fputs(" FOREIGN KEY (", file);
04579
04580 for (i = 0;;) {
04581 ut_print_name(file, trx, FALSE, foreign->foreign_col_names[i]);
04582 if (++i < foreign->n_fields) {
04583 fputs(", ", file);
04584 } else {
04585 break;
04586 }
04587 }
04588
04589 fputs(") REFERENCES ", file);
04590
04591 if (dict_tables_have_same_db(foreign->foreign_table_name,
04592 foreign->referenced_table_name)) {
04593
04594 ut_print_name(file, trx, TRUE,
04595 dict_remove_db_name(
04596 foreign->referenced_table_name));
04597 } else {
04598 ut_print_name(file, trx, TRUE,
04599 foreign->referenced_table_name);
04600 }
04601
04602 putc(' ', file);
04603 putc('(', file);
04604
04605 for (i = 0;;) {
04606 ut_print_name(file, trx, FALSE,
04607 foreign->referenced_col_names[i]);
04608 if (++i < foreign->n_fields) {
04609 fputs(", ", file);
04610 } else {
04611 break;
04612 }
04613 }
04614
04615 putc(')', file);
04616
04617 if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE) {
04618 fputs(" ON DELETE CASCADE", file);
04619 }
04620
04621 if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL) {
04622 fputs(" ON DELETE SET NULL", file);
04623 }
04624
04625 if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION) {
04626 fputs(" ON DELETE NO ACTION", file);
04627 }
04628
04629 if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE) {
04630 fputs(" ON UPDATE CASCADE", file);
04631 }
04632
04633 if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL) {
04634 fputs(" ON UPDATE SET NULL", file);
04635 }
04636
04637 if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION) {
04638 fputs(" ON UPDATE NO ACTION", file);
04639 }
04640 }
04641
04642
04644 UNIV_INTERN
04645 void
04646 dict_print_info_on_foreign_keys(
04647
04648 ibool create_table_format,
04652 FILE* file,
04653 trx_t* trx,
04654 dict_table_t* table)
04655 {
04656 dict_foreign_t* foreign;
04657
04658 mutex_enter(&(dict_sys->mutex));
04659
04660 foreign = UT_LIST_GET_FIRST(table->foreign_list);
04661
04662 if (foreign == NULL) {
04663 mutex_exit(&(dict_sys->mutex));
04664
04665 return;
04666 }
04667
04668 while (foreign != NULL) {
04669 if (create_table_format) {
04670 dict_print_info_on_foreign_key_in_create_format(
04671 file, trx, foreign, TRUE);
04672 } else {
04673 ulint i;
04674 fputs("; (", file);
04675
04676 for (i = 0; i < foreign->n_fields; i++) {
04677 if (i) {
04678 putc(' ', file);
04679 }
04680
04681 ut_print_name(file, trx, FALSE,
04682 foreign->foreign_col_names[i]);
04683 }
04684
04685 fputs(") REFER ", file);
04686 ut_print_name(file, trx, TRUE,
04687 foreign->referenced_table_name);
04688 putc('(', file);
04689
04690 for (i = 0; i < foreign->n_fields; i++) {
04691 if (i) {
04692 putc(' ', file);
04693 }
04694 ut_print_name(
04695 file, trx, FALSE,
04696 foreign->referenced_col_names[i]);
04697 }
04698
04699 putc(')', file);
04700
04701 if (foreign->type == DICT_FOREIGN_ON_DELETE_CASCADE) {
04702 fputs(" ON DELETE CASCADE", file);
04703 }
04704
04705 if (foreign->type == DICT_FOREIGN_ON_DELETE_SET_NULL) {
04706 fputs(" ON DELETE SET NULL", file);
04707 }
04708
04709 if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION) {
04710 fputs(" ON DELETE NO ACTION", file);
04711 }
04712
04713 if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE) {
04714 fputs(" ON UPDATE CASCADE", file);
04715 }
04716
04717 if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL) {
04718 fputs(" ON UPDATE SET NULL", file);
04719 }
04720
04721 if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION) {
04722 fputs(" ON UPDATE NO ACTION", file);
04723 }
04724 }
04725
04726 foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
04727 }
04728
04729 mutex_exit(&(dict_sys->mutex));
04730 }
04731
04732
04734 UNIV_INTERN
04735 void
04736 dict_index_name_print(
04737
04738 FILE* file,
04739 trx_t* trx,
04740 const dict_index_t* index)
04741 {
04742 fputs("index ", file);
04743 ut_print_name(file, trx, FALSE, index->name);
04744 fputs(" of table ", file);
04745 ut_print_name(file, trx, TRUE, index->table_name);
04746 }
04747 #endif
04748
04749
04751 UNIV_INTERN
04752 void
04753 dict_ind_init(void)
04754
04755 {
04756 dict_table_t* table;
04757
04758
04759 table = dict_mem_table_create("SYS_DUMMY1", DICT_HDR_SPACE, 1, 0);
04760 dict_mem_table_add_col(table, NULL, NULL, DATA_CHAR,
04761 DATA_ENGLISH | DATA_NOT_NULL, 8);
04762
04763 dict_ind_redundant = dict_mem_index_create("SYS_DUMMY1", "SYS_DUMMY1",
04764 DICT_HDR_SPACE, 0, 1);
04765 dict_index_add_col(dict_ind_redundant, table,
04766 dict_table_get_nth_col(table, 0), 0);
04767 dict_ind_redundant->table = table;
04768
04769 table = dict_mem_table_create("SYS_DUMMY2",
04770 DICT_HDR_SPACE, 1, DICT_TF_COMPACT);
04771 dict_mem_table_add_col(table, NULL, NULL, DATA_CHAR,
04772 DATA_ENGLISH | DATA_NOT_NULL, 8);
04773 dict_ind_compact = dict_mem_index_create("SYS_DUMMY2", "SYS_DUMMY2",
04774 DICT_HDR_SPACE, 0, 1);
04775 dict_index_add_col(dict_ind_compact, table,
04776 dict_table_get_nth_col(table, 0), 0);
04777 dict_ind_compact->table = table;
04778
04779
04780 dict_ind_redundant->cached = dict_ind_compact->cached = TRUE;
04781 }
04782
04783
04785 static
04786 void
04787 dict_ind_free(void)
04788
04789 {
04790 dict_table_t* table;
04791
04792 table = dict_ind_compact->table;
04793 dict_mem_index_free(dict_ind_compact);
04794 dict_ind_compact = NULL;
04795 dict_mem_table_free(table);
04796
04797 table = dict_ind_redundant->table;
04798 dict_mem_index_free(dict_ind_redundant);
04799 dict_ind_redundant = NULL;
04800 dict_mem_table_free(table);
04801 }
04802
04803 #ifndef UNIV_HOTBACKUP
04804
04807 UNIV_INTERN
04808 dict_index_t*
04809 dict_table_get_index_on_name(
04810
04811 dict_table_t* table,
04812 const char* name)
04813 {
04814 dict_index_t* index;
04815
04816 index = dict_table_get_first_index(table);
04817
04818 while (index != NULL) {
04819 if (ut_strcmp(index->name, name) == 0) {
04820
04821 return(index);
04822 }
04823
04824 index = dict_table_get_next_index(index);
04825 }
04826
04827 return(NULL);
04828
04829 }
04830
04831
04834 UNIV_INTERN
04835 void
04836 dict_table_replace_index_in_foreign_list(
04837
04838 dict_table_t* table,
04839 dict_index_t* index,
04840 const trx_t* trx)
04841 {
04842 dict_foreign_t* foreign;
04843
04844 for (foreign = UT_LIST_GET_FIRST(table->foreign_list);
04845 foreign;
04846 foreign = UT_LIST_GET_NEXT(foreign_list, foreign)) {
04847
04848 if (foreign->foreign_index == index) {
04849 dict_index_t* new_index
04850 = dict_foreign_find_equiv_index(foreign);
04851
04852
04853
04854
04855
04856
04857 ut_a(new_index || !trx->check_foreigns);
04858
04859 foreign->foreign_index = new_index;
04860 }
04861 }
04862 }
04863
04864
04868 UNIV_INTERN
04869 dict_index_t*
04870 dict_table_get_index_on_name_and_min_id(
04871
04872 dict_table_t* table,
04873 const char* name)
04874 {
04875 dict_index_t* index;
04876 dict_index_t* min_index;
04877
04878 min_index = NULL;
04879 index = dict_table_get_first_index(table);
04880
04881 while (index != NULL) {
04882 if (ut_strcmp(index->name, name) == 0) {
04883 if (!min_index || index->id < min_index->id) {
04884
04885 min_index = index;
04886 }
04887 }
04888
04889 index = dict_table_get_next_index(index);
04890 }
04891
04892 return(min_index);
04893
04894 }
04895
04896 #ifdef UNIV_DEBUG
04897
04899 UNIV_INTERN
04900 void
04901 dict_table_check_for_dup_indexes(
04902
04903 const dict_table_t* table,
04905 ibool tmp_ok)
04907 {
04908
04909
04910
04911 const dict_index_t* index1;
04912 const dict_index_t* index2;
04913
04914 ut_ad(mutex_own(&dict_sys->mutex));
04915
04916
04917 ut_a(UT_LIST_GET_LEN(table->indexes) > 0);
04918
04919 index1 = UT_LIST_GET_FIRST(table->indexes);
04920
04921 do {
04922 ut_ad(tmp_ok || *index1->name != TEMP_INDEX_PREFIX);
04923
04924 index2 = UT_LIST_GET_NEXT(indexes, index1);
04925
04926 while (index2) {
04927
04928 if (!index2->to_be_dropped) {
04929 ut_ad(ut_strcmp(index1->name, index2->name));
04930 }
04931
04932 index2 = UT_LIST_GET_NEXT(indexes, index2);
04933 }
04934
04935 index1 = UT_LIST_GET_NEXT(indexes, index1);
04936 } while (index1);
04937 }
04938 #endif
04939
04940
04941
04942 UNIV_INTERN
04943 void
04944 dict_close(void)
04945
04946 {
04947 ulint i;
04948
04949
04950
04951 for (i = 0; i < hash_get_n_cells(dict_sys->table_hash); i++) {
04952 dict_table_t* table;
04953
04954 table = static_cast<dict_table_t *>(HASH_GET_FIRST(dict_sys->table_hash, i));
04955
04956 while (table) {
04957 dict_table_t* prev_table = table;
04958
04959 table = static_cast<dict_table_t *>(HASH_GET_NEXT(name_hash, prev_table));
04960 #ifdef UNIV_DEBUG
04961 ut_a(prev_table->magic_n == DICT_TABLE_MAGIC_N);
04962 #endif
04963
04964 mutex_enter(&dict_sys->mutex);
04965
04966 dict_table_remove_from_cache(prev_table);
04967
04968 mutex_exit(&dict_sys->mutex);
04969 }
04970 }
04971
04972 hash_table_free(dict_sys->table_hash);
04973
04974
04975
04976 hash_table_free(dict_sys->table_id_hash);
04977
04978 dict_ind_free();
04979
04980 mutex_free(&dict_sys->mutex);
04981
04982 rw_lock_free(&dict_operation_lock);
04983 memset(&dict_operation_lock, 0x0, sizeof(dict_operation_lock));
04984
04985 mutex_free(&dict_foreign_err_mutex);
04986
04987 mem_free(dict_sys);
04988 dict_sys = NULL;
04989
04990 for (i = 0; i < DICT_TABLE_STATS_LATCHES_SIZE; i++) {
04991 rw_lock_free(&dict_table_stats_latches[i]);
04992 }
04993 }
04994 #endif