00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00026 #include "dict0crea.h"
00027
00028 #ifdef UNIV_NONINL
00029 #include "dict0crea.ic"
00030 #endif
00031
00032 #include "btr0pcur.h"
00033 #include "btr0btr.h"
00034 #include "page0page.h"
00035 #include "mach0data.h"
00036 #include "dict0boot.h"
00037 #include "dict0dict.h"
00038 #include "que0que.h"
00039 #include "row0ins.h"
00040 #include "row0mysql.h"
00041 #include "pars0pars.h"
00042 #include "trx0roll.h"
00043 #include "usr0sess.h"
00044 #include "ut0vec.h"
00045
00046
00050 static
00051 dtuple_t*
00052 dict_create_sys_tables_tuple(
00053
00054 const dict_table_t* table,
00055 mem_heap_t* heap)
00058 {
00059 dict_table_t* sys_tables;
00060 dtuple_t* entry;
00061 dfield_t* dfield;
00062 byte* ptr;
00063
00064 ut_ad(table);
00065 ut_ad(heap);
00066
00067 sys_tables = dict_sys->sys_tables;
00068
00069 entry = dtuple_create(heap, 8 + DATA_N_SYS_COLS);
00070
00071 dict_table_copy_types(entry, sys_tables);
00072
00073
00074 dfield = dtuple_get_nth_field(entry, 0);
00075
00076 dfield_set_data(dfield, table->name, ut_strlen(table->name));
00077
00078 dfield = dtuple_get_nth_field(entry, 1);
00079
00080 ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
00081 mach_write_to_8(ptr, table->id);
00082
00083 dfield_set_data(dfield, ptr, 8);
00084
00085 dfield = dtuple_get_nth_field(entry, 2);
00086
00087 #if DICT_TF_COMPACT != 1
00088 #error
00089 #endif
00090
00091 ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 4));
00092 mach_write_to_4(ptr, table->n_def
00093 | ((table->flags & DICT_TF_COMPACT) << 31));
00094 dfield_set_data(dfield, ptr, 4);
00095
00096 dfield = dtuple_get_nth_field(entry, 3);
00097
00098 ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 4));
00099 if (table->flags & (~DICT_TF_COMPACT & ~(~0 << DICT_TF_BITS))) {
00100 ut_a(table->flags & DICT_TF_COMPACT);
00101 ut_a(dict_table_get_format(table) >= DICT_TF_FORMAT_ZIP);
00102 ut_a((table->flags & DICT_TF_ZSSIZE_MASK)
00103 <= (DICT_TF_ZSSIZE_MAX << DICT_TF_ZSSIZE_SHIFT));
00104 ut_a(!(table->flags & (~0 << DICT_TF2_BITS)));
00105 mach_write_to_4(ptr, table->flags & ~(~0 << DICT_TF_BITS));
00106 } else {
00107 mach_write_to_4(ptr, DICT_TABLE_ORDINARY);
00108 }
00109
00110 dfield_set_data(dfield, ptr, 4);
00111
00112 dfield = dtuple_get_nth_field(entry, 4);
00113
00114 ptr = static_cast<unsigned char *>(mem_heap_zalloc(heap, 8));
00115
00116 dfield_set_data(dfield, ptr, 8);
00117
00118
00119 dfield = dtuple_get_nth_field(entry, 5);
00120
00121 ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 4));
00122 mach_write_to_4(ptr, table->flags >> DICT_TF2_SHIFT);
00123
00124 dfield_set_data(dfield, ptr, 4);
00125
00126 dfield = dtuple_get_nth_field(entry, 6);
00127 dfield_set_null(dfield);
00128
00129
00130 dfield = dtuple_get_nth_field(entry, 7);
00131
00132 ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 4));
00133 mach_write_to_4(ptr, table->space);
00134
00135 dfield_set_data(dfield, ptr, 4);
00136
00137
00138 return(entry);
00139 }
00140
00141
00145 static
00146 dtuple_t*
00147 dict_create_sys_columns_tuple(
00148
00149 const dict_table_t* table,
00150 ulint i,
00151 mem_heap_t* heap)
00154 {
00155 dict_table_t* sys_columns;
00156 dtuple_t* entry;
00157 const dict_col_t* column;
00158 dfield_t* dfield;
00159 byte* ptr;
00160 const char* col_name;
00161
00162 ut_ad(table);
00163 ut_ad(heap);
00164
00165 column = dict_table_get_nth_col(table, i);
00166
00167 sys_columns = dict_sys->sys_columns;
00168
00169 entry = dtuple_create(heap, 7 + DATA_N_SYS_COLS);
00170
00171 dict_table_copy_types(entry, sys_columns);
00172
00173
00174 dfield = dtuple_get_nth_field(entry, 0);
00175
00176 ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
00177 mach_write_to_8(ptr, table->id);
00178
00179 dfield_set_data(dfield, ptr, 8);
00180
00181 dfield = dtuple_get_nth_field(entry, 1);
00182
00183 ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 4));
00184 mach_write_to_4(ptr, i);
00185
00186 dfield_set_data(dfield, ptr, 4);
00187
00188 dfield = dtuple_get_nth_field(entry, 2);
00189
00190 col_name = dict_table_get_col_name(table, i);
00191 dfield_set_data(dfield, col_name, ut_strlen(col_name));
00192
00193 dfield = dtuple_get_nth_field(entry, 3);
00194
00195 ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 4));
00196 mach_write_to_4(ptr, column->mtype);
00197
00198 dfield_set_data(dfield, ptr, 4);
00199
00200 dfield = dtuple_get_nth_field(entry, 4);
00201
00202 ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 4));
00203 mach_write_to_4(ptr, column->prtype);
00204
00205 dfield_set_data(dfield, ptr, 4);
00206
00207 dfield = dtuple_get_nth_field(entry, 5);
00208
00209 ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 4));
00210 mach_write_to_4(ptr, column->len);
00211
00212 dfield_set_data(dfield, ptr, 4);
00213
00214 dfield = dtuple_get_nth_field(entry, 6);
00215
00216 ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 4));
00217 mach_write_to_4(ptr, 0);
00218
00219 dfield_set_data(dfield, ptr, 4);
00220
00221
00222 return(entry);
00223 }
00224
00225
00228 static
00229 ulint
00230 dict_build_table_def_step(
00231
00232 que_thr_t* thr,
00233 tab_node_t* node)
00234 {
00235 dict_table_t* table;
00236 dtuple_t* row;
00237 ulint error;
00238 ulint flags;
00239 const char* path_or_name;
00240 ibool is_path;
00241 mtr_t mtr;
00242 ulint space = 0;
00243 ibool file_per_table;
00244
00245 ut_ad(mutex_own(&(dict_sys->mutex)));
00246
00247 table = node->table;
00248
00249
00250
00251
00252
00253
00254
00255
00256 file_per_table = srv_file_per_table;
00257
00258 dict_hdr_get_new_id(&table->id, NULL, NULL);
00259
00260 thr_get_trx(thr)->table_id = table->id;
00261
00262 if (file_per_table) {
00263
00264 dict_hdr_get_new_id(NULL, NULL, &space);
00265
00266 if (UNIV_UNLIKELY(space == ULINT_UNDEFINED)) {
00267 return(DB_ERROR);
00268 }
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278 if (table->dir_path_of_temp_table) {
00279
00280
00281
00282 path_or_name = table->dir_path_of_temp_table;
00283 is_path = TRUE;
00284 } else {
00285 path_or_name = table->name;
00286 is_path = FALSE;
00287 }
00288
00289 ut_ad(dict_table_get_format(table) <= DICT_TF_FORMAT_MAX);
00290 ut_ad(!dict_table_zip_size(table)
00291 || dict_table_get_format(table) >= DICT_TF_FORMAT_ZIP);
00292
00293 flags = table->flags & ~(~0 << DICT_TF_BITS);
00294 error = fil_create_new_single_table_tablespace(
00295 space, path_or_name, is_path,
00296 flags == DICT_TF_COMPACT ? 0 : flags,
00297 FIL_IBD_FILE_INITIAL_SIZE);
00298 table->space = (unsigned int) space;
00299
00300 if (error != DB_SUCCESS) {
00301
00302 return(error);
00303 }
00304
00305 mtr_start(&mtr);
00306
00307 fsp_header_init(table->space, FIL_IBD_FILE_INITIAL_SIZE, &mtr);
00308
00309 mtr_commit(&mtr);
00310 } else {
00311
00312 table->flags &= (~0 << DICT_TF_BITS) | DICT_TF_COMPACT;
00313 }
00314
00315 row = dict_create_sys_tables_tuple(table, node->heap);
00316
00317 ins_node_set_new_row(node->tab_def, row);
00318
00319 return(DB_SUCCESS);
00320 }
00321
00322
00325 static
00326 ulint
00327 dict_build_col_def_step(
00328
00329 tab_node_t* node)
00330 {
00331 dtuple_t* row;
00332
00333 row = dict_create_sys_columns_tuple(node->table, node->col_no,
00334 node->heap);
00335 ins_node_set_new_row(node->col_def, row);
00336
00337 return(DB_SUCCESS);
00338 }
00339
00340
00344 static
00345 dtuple_t*
00346 dict_create_sys_indexes_tuple(
00347
00348 const dict_index_t* index,
00349 mem_heap_t* heap)
00352 {
00353 dict_table_t* sys_indexes;
00354 dict_table_t* table;
00355 dtuple_t* entry;
00356 dfield_t* dfield;
00357 byte* ptr;
00358
00359 ut_ad(mutex_own(&(dict_sys->mutex)));
00360 ut_ad(index);
00361 ut_ad(heap);
00362
00363 sys_indexes = dict_sys->sys_indexes;
00364
00365 table = dict_table_get_low(index->table_name);
00366
00367 entry = dtuple_create(heap, 7 + DATA_N_SYS_COLS);
00368
00369 dict_table_copy_types(entry, sys_indexes);
00370
00371
00372 dfield = dtuple_get_nth_field(entry, 0);
00373
00374 ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
00375 mach_write_to_8(ptr, table->id);
00376
00377 dfield_set_data(dfield, ptr, 8);
00378
00379 dfield = dtuple_get_nth_field(entry, 1);
00380
00381 ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
00382 mach_write_to_8(ptr, index->id);
00383
00384 dfield_set_data(dfield, ptr, 8);
00385
00386 dfield = dtuple_get_nth_field(entry, 2);
00387
00388 dfield_set_data(dfield, index->name, ut_strlen(index->name));
00389
00390 dfield = dtuple_get_nth_field(entry, 3);
00391
00392 ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 4));
00393 mach_write_to_4(ptr, index->n_fields);
00394
00395 dfield_set_data(dfield, ptr, 4);
00396
00397 dfield = dtuple_get_nth_field(entry, 4);
00398
00399 ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 4));
00400 mach_write_to_4(ptr, index->type);
00401
00402 dfield_set_data(dfield, ptr, 4);
00403
00404
00405 #if DICT_SYS_INDEXES_SPACE_NO_FIELD != 7
00406 #error "DICT_SYS_INDEXES_SPACE_NO_FIELD != 7"
00407 #endif
00408
00409 dfield = dtuple_get_nth_field(entry, 5);
00410
00411 ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 4));
00412 mach_write_to_4(ptr, index->space);
00413
00414 dfield_set_data(dfield, ptr, 4);
00415
00416
00417 #if DICT_SYS_INDEXES_PAGE_NO_FIELD != 8
00418 #error "DICT_SYS_INDEXES_PAGE_NO_FIELD != 8"
00419 #endif
00420
00421 dfield = dtuple_get_nth_field(entry, 6);
00422
00423 ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 4));
00424 mach_write_to_4(ptr, FIL_NULL);
00425
00426 dfield_set_data(dfield, ptr, 4);
00427
00428
00429 return(entry);
00430 }
00431
00432
00436 static
00437 dtuple_t*
00438 dict_create_sys_fields_tuple(
00439
00440 const dict_index_t* index,
00441 ulint i,
00442 mem_heap_t* heap)
00445 {
00446 dict_table_t* sys_fields;
00447 dtuple_t* entry;
00448 dict_field_t* field;
00449 dfield_t* dfield;
00450 byte* ptr;
00451 ibool index_contains_column_prefix_field = FALSE;
00452 ulint j;
00453
00454 ut_ad(index);
00455 ut_ad(heap);
00456
00457 for (j = 0; j < index->n_fields; j++) {
00458 if (dict_index_get_nth_field(index, j)->prefix_len > 0) {
00459 index_contains_column_prefix_field = TRUE;
00460 break;
00461 }
00462 }
00463
00464 field = dict_index_get_nth_field(index, i);
00465
00466 sys_fields = dict_sys->sys_fields;
00467
00468 entry = dtuple_create(heap, 3 + DATA_N_SYS_COLS);
00469
00470 dict_table_copy_types(entry, sys_fields);
00471
00472
00473 dfield = dtuple_get_nth_field(entry, 0);
00474
00475 ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
00476 mach_write_to_8(ptr, index->id);
00477
00478 dfield_set_data(dfield, ptr, 8);
00479
00480
00481 dfield = dtuple_get_nth_field(entry, 1);
00482
00483 ptr = static_cast<unsigned char *>(mem_heap_alloc(heap, 4));
00484
00485 if (index_contains_column_prefix_field) {
00486
00487
00488
00489
00490 mach_write_to_4(ptr, (i << 16) + field->prefix_len);
00491 } else {
00492
00493
00494
00495
00496 mach_write_to_4(ptr, i);
00497 }
00498
00499 dfield_set_data(dfield, ptr, 4);
00500
00501 dfield = dtuple_get_nth_field(entry, 2);
00502
00503 dfield_set_data(dfield, field->name,
00504 ut_strlen(field->name));
00505
00506
00507 return(entry);
00508 }
00509
00510
00514 static
00515 dtuple_t*
00516 dict_create_search_tuple(
00517
00518 const dtuple_t* tuple,
00520 mem_heap_t* heap)
00522 {
00523 dtuple_t* search_tuple;
00524 const dfield_t* field1;
00525 dfield_t* field2;
00526
00527 ut_ad(tuple && heap);
00528
00529 search_tuple = dtuple_create(heap, 2);
00530
00531 field1 = dtuple_get_nth_field(tuple, 0);
00532 field2 = dtuple_get_nth_field(search_tuple, 0);
00533
00534 dfield_copy(field2, field1);
00535
00536 field1 = dtuple_get_nth_field(tuple, 1);
00537 field2 = dtuple_get_nth_field(search_tuple, 1);
00538
00539 dfield_copy(field2, field1);
00540
00541 ut_ad(dtuple_validate(search_tuple));
00542
00543 return(search_tuple);
00544 }
00545
00546
00549 static
00550 ulint
00551 dict_build_index_def_step(
00552
00553 que_thr_t* thr,
00554 ind_node_t* node)
00555 {
00556 dict_table_t* table;
00557 dict_index_t* index;
00558 dtuple_t* row;
00559 trx_t* trx;
00560
00561 ut_ad(mutex_own(&(dict_sys->mutex)));
00562
00563 trx = thr_get_trx(thr);
00564
00565 index = node->index;
00566
00567 table = dict_table_get_low(index->table_name);
00568
00569 if (table == NULL) {
00570 return(DB_TABLE_NOT_FOUND);
00571 }
00572
00573 trx->table_id = table->id;
00574
00575 node->table = table;
00576
00577 ut_ad((UT_LIST_GET_LEN(table->indexes) > 0)
00578 || dict_index_is_clust(index));
00579
00580 dict_hdr_get_new_id(NULL, &index->id, NULL);
00581
00582
00583
00584
00585 index->space = table->space;
00586 node->page_no = FIL_NULL;
00587 row = dict_create_sys_indexes_tuple(index, node->heap);
00588 node->ind_row = row;
00589
00590 ins_node_set_new_row(node->ind_def, row);
00591
00592
00593 index->trx_id = trx->id;
00594
00595 return(DB_SUCCESS);
00596 }
00597
00598
00601 static
00602 ulint
00603 dict_build_field_def_step(
00604
00605 ind_node_t* node)
00606 {
00607 dict_index_t* index;
00608 dtuple_t* row;
00609
00610 index = node->index;
00611
00612 row = dict_create_sys_fields_tuple(index, node->field_no, node->heap);
00613
00614 ins_node_set_new_row(node->field_def, row);
00615
00616 return(DB_SUCCESS);
00617 }
00618
00619
00622 static
00623 ulint
00624 dict_create_index_tree_step(
00625
00626 ind_node_t* node)
00627 {
00628 dict_index_t* index;
00629 dict_table_t* sys_indexes;
00630 dtuple_t* search_tuple;
00631 ulint zip_size;
00632 btr_pcur_t pcur;
00633 mtr_t mtr;
00634
00635 ut_ad(mutex_own(&(dict_sys->mutex)));
00636
00637 index = node->index;
00638
00639 sys_indexes = dict_sys->sys_indexes;
00640
00641
00642
00643
00644
00645 mtr_start(&mtr);
00646
00647 search_tuple = dict_create_search_tuple(node->ind_row, node->heap);
00648
00649 btr_pcur_open(UT_LIST_GET_FIRST(sys_indexes->indexes),
00650 search_tuple, PAGE_CUR_L, BTR_MODIFY_LEAF,
00651 &pcur, &mtr);
00652
00653 btr_pcur_move_to_next_user_rec(&pcur, &mtr);
00654
00655 zip_size = dict_table_zip_size(index->table);
00656
00657 node->page_no = btr_create(index->type, index->space, zip_size,
00658 index->id, index, &mtr);
00659
00660
00661
00662 page_rec_write_index_page_no(btr_pcur_get_rec(&pcur),
00663 DICT_SYS_INDEXES_PAGE_NO_FIELD,
00664 node->page_no, &mtr);
00665 btr_pcur_close(&pcur);
00666 mtr_commit(&mtr);
00667
00668 if (node->page_no == FIL_NULL) {
00669
00670 return(DB_OUT_OF_FILE_SPACE);
00671 }
00672
00673 return(DB_SUCCESS);
00674 }
00675
00676
00678 UNIV_INTERN
00679 void
00680 dict_drop_index_tree(
00681
00682 rec_t* rec,
00684 mtr_t* mtr)
00685 {
00686 ulint root_page_no;
00687 ulint space;
00688 ulint zip_size;
00689 const byte* ptr;
00690 ulint len;
00691
00692 ut_ad(mutex_own(&(dict_sys->mutex)));
00693 ut_a(!dict_table_is_comp(dict_sys->sys_indexes));
00694 ptr = rec_get_nth_field_old(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD, &len);
00695
00696 ut_ad(len == 4);
00697
00698 root_page_no = mtr_read_ulint(ptr, MLOG_4BYTES, mtr);
00699
00700 if (root_page_no == FIL_NULL) {
00701
00702
00703 return;
00704 }
00705
00706 ptr = rec_get_nth_field_old(rec,
00707 DICT_SYS_INDEXES_SPACE_NO_FIELD, &len);
00708
00709 ut_ad(len == 4);
00710
00711 space = mtr_read_ulint(ptr, MLOG_4BYTES, mtr);
00712 zip_size = fil_space_get_zip_size(space);
00713
00714 if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) {
00715
00716
00717
00718 return;
00719 }
00720
00721
00722
00723
00724 btr_free_but_not_root(space, zip_size, root_page_no);
00725
00726
00727
00728
00729
00730
00731
00732 btr_free_root(space, zip_size, root_page_no, mtr);
00733
00734 page_rec_write_index_page_no(rec,
00735 DICT_SYS_INDEXES_PAGE_NO_FIELD,
00736 FIL_NULL, mtr);
00737 }
00738
00739
00742 UNIV_INTERN
00743 ulint
00744 dict_truncate_index_tree(
00745
00746 dict_table_t* table,
00747 ulint space,
00750 btr_pcur_t* pcur,
00754 mtr_t* mtr)
00757 {
00758 ulint root_page_no;
00759 ibool drop = !space;
00760 ulint zip_size;
00761 ulint type;
00762 index_id_t index_id;
00763 rec_t* rec;
00764 const byte* ptr;
00765 ulint len;
00766 dict_index_t* index;
00767
00768 ut_ad(mutex_own(&(dict_sys->mutex)));
00769 ut_a(!dict_table_is_comp(dict_sys->sys_indexes));
00770 rec = btr_pcur_get_rec(pcur);
00771 ptr = rec_get_nth_field_old(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD, &len);
00772
00773 ut_ad(len == 4);
00774
00775 root_page_no = mtr_read_ulint(ptr, MLOG_4BYTES, mtr);
00776
00777 if (drop && root_page_no == FIL_NULL) {
00778
00779
00780 ut_print_timestamp(stderr);
00781 fprintf(stderr, " InnoDB: Trying to TRUNCATE"
00782 " a missing index of table %s!\n", table->name);
00783 drop = FALSE;
00784 }
00785
00786 ptr = rec_get_nth_field_old(rec,
00787 DICT_SYS_INDEXES_SPACE_NO_FIELD, &len);
00788
00789 ut_ad(len == 4);
00790
00791 if (drop) {
00792 space = mtr_read_ulint(ptr, MLOG_4BYTES, mtr);
00793 }
00794
00795 zip_size = fil_space_get_zip_size(space);
00796
00797 if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) {
00798
00799
00800
00801 ut_print_timestamp(stderr);
00802 fprintf(stderr, " InnoDB: Trying to TRUNCATE"
00803 " a missing .ibd file of table %s!\n", table->name);
00804 return(FIL_NULL);
00805 }
00806
00807 ptr = rec_get_nth_field_old(rec,
00808 DICT_SYS_INDEXES_TYPE_FIELD, &len);
00809 ut_ad(len == 4);
00810 type = mach_read_from_4(ptr);
00811
00812 ptr = rec_get_nth_field_old(rec, 1, &len);
00813 ut_ad(len == 8);
00814 index_id = mach_read_from_8(ptr);
00815
00816 if (!drop) {
00817
00818 goto create;
00819 }
00820
00821
00822
00823
00824 btr_free_but_not_root(space, zip_size, root_page_no);
00825
00826
00827
00828
00829
00830
00831 btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, mtr);
00832
00833 btr_free_root(space, zip_size, root_page_no, mtr);
00834 create:
00835
00836
00837
00838
00839 page_rec_write_index_page_no(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD,
00840 FIL_NULL, mtr);
00841
00842
00843
00844
00845 btr_pcur_store_position(pcur, mtr);
00846 mtr_commit(mtr);
00847
00848 mtr_start(mtr);
00849 btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur, mtr);
00850
00851
00852 for (index = UT_LIST_GET_FIRST(table->indexes);
00853 index;
00854 index = UT_LIST_GET_NEXT(indexes, index)) {
00855 if (index->id == index_id) {
00856 root_page_no = btr_create(type, space, zip_size,
00857 index_id, index, mtr);
00858 index->page = (unsigned int) root_page_no;
00859 return(root_page_no);
00860 }
00861 }
00862
00863 ut_print_timestamp(stderr);
00864 fprintf(stderr,
00865 " InnoDB: Index %llu of table %s is missing\n"
00866 "InnoDB: from the data dictionary during TRUNCATE!\n",
00867 (ullint) index_id,
00868 table->name);
00869
00870 return(FIL_NULL);
00871 }
00872
00873
00876 UNIV_INTERN
00877 tab_node_t*
00878 tab_create_graph_create(
00879
00880 dict_table_t* table,
00882 mem_heap_t* heap)
00883 {
00884 tab_node_t* node;
00885
00886 node = static_cast<tab_node_t *>(mem_heap_alloc(heap, sizeof(tab_node_t)));
00887
00888 node->common.type = QUE_NODE_CREATE_TABLE;
00889
00890 node->table = table;
00891
00892 node->state = TABLE_BUILD_TABLE_DEF;
00893 node->heap = mem_heap_create(256);
00894
00895 node->tab_def = ins_node_create(INS_DIRECT, dict_sys->sys_tables,
00896 heap);
00897 node->tab_def->common.parent = node;
00898
00899 node->col_def = ins_node_create(INS_DIRECT, dict_sys->sys_columns,
00900 heap);
00901 node->col_def->common.parent = node;
00902
00903 node->commit_node = commit_node_create(heap);
00904 node->commit_node->common.parent = node;
00905
00906 return(node);
00907 }
00908
00909
00912 UNIV_INTERN
00913 ind_node_t*
00914 ind_create_graph_create(
00915
00916 dict_index_t* index,
00918 mem_heap_t* heap)
00919 {
00920 ind_node_t* node;
00921
00922 node = static_cast<ind_node_t *>(mem_heap_alloc(heap, sizeof(ind_node_t)));
00923
00924 node->common.type = QUE_NODE_CREATE_INDEX;
00925
00926 node->index = index;
00927
00928 node->state = INDEX_BUILD_INDEX_DEF;
00929 node->page_no = FIL_NULL;
00930 node->heap = mem_heap_create(256);
00931
00932 node->ind_def = ins_node_create(INS_DIRECT,
00933 dict_sys->sys_indexes, heap);
00934 node->ind_def->common.parent = node;
00935
00936 node->field_def = ins_node_create(INS_DIRECT,
00937 dict_sys->sys_fields, heap);
00938 node->field_def->common.parent = node;
00939
00940 node->commit_node = commit_node_create(heap);
00941 node->commit_node->common.parent = node;
00942
00943 return(node);
00944 }
00945
00946
00949 UNIV_INTERN
00950 que_thr_t*
00951 dict_create_table_step(
00952
00953 que_thr_t* thr)
00954 {
00955 tab_node_t* node;
00956 ulint err = DB_ERROR;
00957 trx_t* trx;
00958
00959 ut_ad(thr);
00960 ut_ad(mutex_own(&(dict_sys->mutex)));
00961
00962 trx = thr_get_trx(thr);
00963
00964 node = static_cast<tab_node_t *>(thr->run_node);
00965
00966 ut_ad(que_node_get_type(node) == QUE_NODE_CREATE_TABLE);
00967
00968 if (thr->prev_node == que_node_get_parent(node)) {
00969 node->state = TABLE_BUILD_TABLE_DEF;
00970 }
00971
00972 if (node->state == TABLE_BUILD_TABLE_DEF) {
00973
00974
00975
00976 err = dict_build_table_def_step(thr, node);
00977
00978 if (err != DB_SUCCESS) {
00979
00980 goto function_exit;
00981 }
00982
00983 node->state = TABLE_BUILD_COL_DEF;
00984 node->col_no = 0;
00985
00986 thr->run_node = node->tab_def;
00987
00988 return(thr);
00989 }
00990
00991 if (node->state == TABLE_BUILD_COL_DEF) {
00992
00993 if (node->col_no < (node->table)->n_def) {
00994
00995 err = dict_build_col_def_step(node);
00996
00997 if (err != DB_SUCCESS) {
00998
00999 goto function_exit;
01000 }
01001
01002 node->col_no++;
01003
01004 thr->run_node = node->col_def;
01005
01006 return(thr);
01007 } else {
01008 node->state = TABLE_COMMIT_WORK;
01009 }
01010 }
01011
01012 if (node->state == TABLE_COMMIT_WORK) {
01013
01014
01015
01016
01017
01018 node->state = TABLE_ADD_TO_CACHE;
01019
01020
01021
01022
01023 }
01024
01025 if (node->state == TABLE_ADD_TO_CACHE) {
01026
01027 dict_table_add_to_cache(node->table, node->heap);
01028
01029 err = DB_SUCCESS;
01030 }
01031
01032 function_exit:
01033 trx->error_state = err;
01034
01035 if (err == DB_SUCCESS) {
01036
01037
01038 } else if (err == DB_LOCK_WAIT) {
01039
01040 return(NULL);
01041 } else {
01042
01043
01044 return(NULL);
01045 }
01046
01047 thr->run_node = que_node_get_parent(node);
01048
01049 return(thr);
01050 }
01051
01052
01056 UNIV_INTERN
01057 que_thr_t*
01058 dict_create_index_step(
01059
01060 que_thr_t* thr)
01061 {
01062 ind_node_t* node;
01063 ulint err = DB_ERROR;
01064 trx_t* trx;
01065
01066 ut_ad(thr);
01067 ut_ad(mutex_own(&(dict_sys->mutex)));
01068
01069 trx = thr_get_trx(thr);
01070
01071 node = static_cast<ind_node_t *>(thr->run_node);
01072
01073 ut_ad(que_node_get_type(node) == QUE_NODE_CREATE_INDEX);
01074
01075 if (thr->prev_node == que_node_get_parent(node)) {
01076 node->state = INDEX_BUILD_INDEX_DEF;
01077 }
01078
01079 if (node->state == INDEX_BUILD_INDEX_DEF) {
01080
01081 err = dict_build_index_def_step(thr, node);
01082
01083 if (err != DB_SUCCESS) {
01084
01085 goto function_exit;
01086 }
01087
01088 node->state = INDEX_BUILD_FIELD_DEF;
01089 node->field_no = 0;
01090
01091 thr->run_node = node->ind_def;
01092
01093 return(thr);
01094 }
01095
01096 if (node->state == INDEX_BUILD_FIELD_DEF) {
01097
01098 if (node->field_no < (node->index)->n_fields) {
01099
01100 err = dict_build_field_def_step(node);
01101
01102 if (err != DB_SUCCESS) {
01103
01104 goto function_exit;
01105 }
01106
01107 node->field_no++;
01108
01109 thr->run_node = node->field_def;
01110
01111 return(thr);
01112 } else {
01113 node->state = INDEX_ADD_TO_CACHE;
01114 }
01115 }
01116
01117 if (node->state == INDEX_ADD_TO_CACHE) {
01118
01119 index_id_t index_id = node->index->id;
01120
01121 err = dict_index_add_to_cache(
01122 node->table, node->index, FIL_NULL,
01123 trx_is_strict(trx)
01124 || dict_table_get_format(node->table)
01125 >= DICT_TF_FORMAT_ZIP);
01126
01127 node->index = dict_index_get_if_in_cache_low(index_id);
01128 ut_a(!node->index == (err != DB_SUCCESS));
01129
01130 if (err != DB_SUCCESS) {
01131
01132 goto function_exit;
01133 }
01134
01135 node->state = INDEX_CREATE_INDEX_TREE;
01136 }
01137
01138 if (node->state == INDEX_CREATE_INDEX_TREE) {
01139
01140 err = dict_create_index_tree_step(node);
01141
01142 if (err != DB_SUCCESS) {
01143 dict_index_remove_from_cache(node->table, node->index);
01144 node->index = NULL;
01145
01146 goto function_exit;
01147 }
01148
01149 node->index->page = node->page_no;
01150 node->state = INDEX_COMMIT_WORK;
01151 }
01152
01153 if (node->state == INDEX_COMMIT_WORK) {
01154
01155
01156
01157
01158
01159 node->state = INDEX_CREATE_INDEX_TREE;
01160
01161
01162
01163
01164 }
01165
01166 function_exit:
01167 trx->error_state = err;
01168
01169 if (err == DB_SUCCESS) {
01170
01171
01172 } else if (err == DB_LOCK_WAIT) {
01173
01174 return(NULL);
01175 } else {
01176
01177
01178 return(NULL);
01179 }
01180
01181 thr->run_node = que_node_get_parent(node);
01182
01183 return(thr);
01184 }
01185
01186
01191 UNIV_INTERN
01192 ulint
01193 dict_create_or_check_foreign_constraint_tables(void)
01194
01195 {
01196 dict_table_t* table1;
01197 dict_table_t* table2;
01198 ulint error;
01199 trx_t* trx;
01200
01201 mutex_enter(&(dict_sys->mutex));
01202
01203 table1 = dict_table_get_low("SYS_FOREIGN");
01204 table2 = dict_table_get_low("SYS_FOREIGN_COLS");
01205
01206 if (table1 && table2
01207 && UT_LIST_GET_LEN(table1->indexes) == 3
01208 && UT_LIST_GET_LEN(table2->indexes) == 1) {
01209
01210
01211
01212
01213 mutex_exit(&(dict_sys->mutex));
01214
01215 return(DB_SUCCESS);
01216 }
01217
01218 mutex_exit(&(dict_sys->mutex));
01219
01220 trx = trx_allocate_for_mysql();
01221
01222 trx->op_info = "creating foreign key sys tables";
01223
01224 row_mysql_lock_data_dictionary(trx);
01225
01226 if (table1) {
01227 fprintf(stderr,
01228 "InnoDB: dropping incompletely created"
01229 " SYS_FOREIGN table\n");
01230 row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE);
01231 }
01232
01233 if (table2) {
01234 fprintf(stderr,
01235 "InnoDB: dropping incompletely created"
01236 " SYS_FOREIGN_COLS table\n");
01237 row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE);
01238 }
01239
01240 fprintf(stderr,
01241 "InnoDB: Creating foreign key constraint system tables\n");
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253 pars_info_t *info = pars_info_create();
01254 error = que_eval_sql(info,
01255 "PROCEDURE CREATE_FOREIGN_SYS_TABLES_PROC () IS\n"
01256 "BEGIN\n"
01257 "CREATE TABLE\n"
01258 "SYS_FOREIGN(ID CHAR, FOR_NAME CHAR,"
01259 " REF_NAME CHAR, N_COLS INT);\n"
01260 "CREATE UNIQUE CLUSTERED INDEX ID_IND"
01261 " ON SYS_FOREIGN (ID);\n"
01262 "CREATE INDEX FOR_IND"
01263 " ON SYS_FOREIGN (FOR_NAME);\n"
01264 "CREATE INDEX REF_IND"
01265 " ON SYS_FOREIGN (REF_NAME);\n"
01266 "CREATE TABLE\n"
01267 "SYS_FOREIGN_COLS(ID CHAR, POS INT,"
01268 " FOR_COL_NAME CHAR, REF_COL_NAME CHAR);\n"
01269 "CREATE UNIQUE CLUSTERED INDEX ID_IND"
01270 " ON SYS_FOREIGN_COLS (ID, POS);\n"
01271 "END;\n"
01272 , FALSE, trx);
01273
01274 if (error != DB_SUCCESS) {
01275 fprintf(stderr, "InnoDB: error %lu in creation\n",
01276 (ulong) error);
01277
01278 ut_a(error == DB_OUT_OF_FILE_SPACE
01279 || error == DB_TOO_MANY_CONCURRENT_TRXS);
01280
01281 fprintf(stderr,
01282 "InnoDB: creation failed\n"
01283 "InnoDB: tablespace is full\n"
01284 "InnoDB: dropping incompletely created"
01285 " SYS_FOREIGN tables\n");
01286
01287 row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE);
01288 row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE);
01289
01290 error = DB_MUST_GET_MORE_FILE_SPACE;
01291 }
01292
01293 trx_commit_for_mysql(trx);
01294
01295 row_mysql_unlock_data_dictionary(trx);
01296
01297 trx_free_for_mysql(trx);
01298
01299 if (error == DB_SUCCESS) {
01300 fprintf(stderr,
01301 "InnoDB: Foreign key constraint system tables"
01302 " created\n");
01303 }
01304
01305 return(error);
01306 }
01307
01308
01311 static
01312 ulint
01313 dict_foreign_eval_sql(
01314
01315 pars_info_t* info,
01316 const char* sql,
01317 dict_table_t* table,
01318 dict_foreign_t* foreign,
01319 trx_t* trx)
01320 {
01321 ulint error;
01322 FILE* ef = dict_foreign_err_file;
01323
01324 error = que_eval_sql(info, sql, FALSE, trx);
01325
01326 if (error == DB_DUPLICATE_KEY) {
01327 mutex_enter(&dict_foreign_err_mutex);
01328 rewind(ef);
01329 ut_print_timestamp(ef);
01330 fputs(" Error in foreign key constraint creation for table ",
01331 ef);
01332 ut_print_name(ef, trx, TRUE, table->name);
01333 fputs(".\nA foreign key constraint of name ", ef);
01334 ut_print_name(ef, trx, TRUE, foreign->id);
01335 fputs("\nalready exists."
01336 " (Note that internally InnoDB adds 'databasename'\n"
01337 "in front of the user-defined constraint name.)\n"
01338 "Note that InnoDB's FOREIGN KEY system tables store\n"
01339 "constraint names as case-insensitive, with the\n"
01340 "MySQL standard latin1_swedish_ci collation. If you\n"
01341 "create tables or databases whose names differ only in\n"
01342 "the character case, then collisions in constraint\n"
01343 "names can occur. Workaround: name your constraints\n"
01344 "explicitly with unique names.\n",
01345 ef);
01346
01347 mutex_exit(&dict_foreign_err_mutex);
01348
01349 return(error);
01350 }
01351
01352 if (error != DB_SUCCESS) {
01353 fprintf(stderr,
01354 "InnoDB: Foreign key constraint creation failed:\n"
01355 "InnoDB: internal error number %lu\n", (ulong) error);
01356
01357 mutex_enter(&dict_foreign_err_mutex);
01358 ut_print_timestamp(ef);
01359 fputs(" Internal error in foreign key constraint creation"
01360 " for table ", ef);
01361 ut_print_name(ef, trx, TRUE, table->name);
01362 fputs(".\n"
01363 "See the MySQL .err log in the datadir"
01364 " for more information.\n", ef);
01365 mutex_exit(&dict_foreign_err_mutex);
01366
01367 return(error);
01368 }
01369
01370 return(DB_SUCCESS);
01371 }
01372
01373
01377 static
01378 ulint
01379 dict_create_add_foreign_field_to_dictionary(
01380
01381 ulint field_nr,
01382 dict_table_t* table,
01383 dict_foreign_t* foreign,
01384 trx_t* trx)
01385 {
01386 pars_info_t* info = pars_info_create();
01387
01388 pars_info_add_str_literal(info, "id", foreign->id);
01389
01390 pars_info_add_int4_literal(info, "pos", field_nr);
01391
01392 pars_info_add_str_literal(info, "for_col_name",
01393 foreign->foreign_col_names[field_nr]);
01394
01395 pars_info_add_str_literal(info, "ref_col_name",
01396 foreign->referenced_col_names[field_nr]);
01397
01398 return(dict_foreign_eval_sql(
01399 info,
01400 "PROCEDURE P () IS\n"
01401 "BEGIN\n"
01402 "INSERT INTO SYS_FOREIGN_COLS VALUES"
01403 "(:id, :pos, :for_col_name, :ref_col_name);\n"
01404 "END;\n",
01405 table, foreign, trx));
01406 }
01407
01408
01416 static
01417 ulint
01418 dict_create_add_foreign_to_dictionary(
01419
01420 ulint* id_nr,
01422 dict_table_t* table,
01423 dict_foreign_t* foreign,
01424 trx_t* trx)
01425 {
01426 ulint error;
01427 ulint i;
01428
01429 pars_info_t* info = pars_info_create();
01430
01431 if (foreign->id == NULL) {
01432
01433 ulint namelen = strlen(table->name);
01434 char* id = static_cast<char *>(mem_heap_alloc(foreign->heap, namelen + 20));
01435
01436 sprintf(id, "%s_ibfk_%lu", table->name, (ulong) (*id_nr)++);
01437 foreign->id = id;
01438 }
01439
01440 pars_info_add_str_literal(info, "id", foreign->id);
01441
01442 pars_info_add_str_literal(info, "for_name", table->name);
01443
01444 pars_info_add_str_literal(info, "ref_name",
01445 foreign->referenced_table_name);
01446
01447 pars_info_add_int4_literal(info, "n_cols",
01448 foreign->n_fields + (foreign->type << 24));
01449
01450 error = dict_foreign_eval_sql(info,
01451 "PROCEDURE P () IS\n"
01452 "BEGIN\n"
01453 "INSERT INTO SYS_FOREIGN VALUES"
01454 "(:id, :for_name, :ref_name, :n_cols);\n"
01455 "END;\n"
01456 , table, foreign, trx);
01457
01458 if (error != DB_SUCCESS) {
01459
01460 return(error);
01461 }
01462
01463 for (i = 0; i < foreign->n_fields; i++) {
01464 error = dict_create_add_foreign_field_to_dictionary(
01465 i, table, foreign, trx);
01466
01467 if (error != DB_SUCCESS) {
01468
01469 return(error);
01470 }
01471 }
01472
01473 error = dict_foreign_eval_sql(NULL,
01474 "PROCEDURE P () IS\n"
01475 "BEGIN\n"
01476 "COMMIT WORK;\n"
01477 "END;\n"
01478 , table, foreign, trx);
01479
01480 return(error);
01481 }
01482
01483
01486 UNIV_INTERN
01487 ulint
01488 dict_create_add_foreigns_to_dictionary(
01489
01490 ulint start_id,
01498 dict_table_t* table,
01499 trx_t* trx)
01500 {
01501 dict_foreign_t* foreign;
01502 ulint number = start_id + 1;
01503 ulint error;
01504
01505 ut_ad(mutex_own(&(dict_sys->mutex)));
01506
01507 if (NULL == dict_table_get_low("SYS_FOREIGN")) {
01508 fprintf(stderr,
01509 "InnoDB: table SYS_FOREIGN not found"
01510 " in internal data dictionary\n");
01511
01512 return(DB_ERROR);
01513 }
01514
01515 for (foreign = UT_LIST_GET_FIRST(table->foreign_list);
01516 foreign;
01517 foreign = UT_LIST_GET_NEXT(foreign_list, foreign)) {
01518
01519 error = dict_create_add_foreign_to_dictionary(&number, table,
01520 foreign, trx);
01521
01522 if (error != DB_SUCCESS) {
01523
01524 return(error);
01525 }
01526 }
01527
01528 return(DB_SUCCESS);
01529 }