00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00024 #include <config.h>
00025 #include <drizzled/error.h>
00026 #include <drizzled/charset_info.h>
00027 #include <drizzled/field.h>
00028 #include <drizzled/table.h>
00029 #include <drizzled/field/varstring.h>
00030 #include <drizzled/internal/my_sys.h>
00031
00032 #include "log0log.h"
00033 #include "row0merge.h"
00034 #include "srv0srv.h"
00035 #include "trx0trx.h"
00036 #include "trx0roll.h"
00037 #include "ha_prototypes.h"
00038 #include "handler0alter.h"
00039
00040 #include "ha_innodb.h"
00041 #include "handler0vars.h"
00042
00043
00046 static
00047 void
00048 innobase_col_to_mysql(
00049
00050 const dict_col_t* col,
00051 const unsigned char* data,
00052 ulint len,
00053 Field* field)
00054 {
00055 unsigned char* ptr;
00056 unsigned char* dest = field->ptr;
00057 ulint flen = field->pack_length();
00058
00059 switch (col->mtype) {
00060 case DATA_INT:
00061 ut_ad(len == flen);
00062
00063
00064
00065
00066 for (ptr = dest + len; ptr != dest; ) {
00067 *--ptr = *data++;
00068 }
00069
00070 if (!(field->flags & UNSIGNED_FLAG)) {
00071 ((byte*) dest)[len - 1] ^= 0x80;
00072 }
00073
00074 break;
00075
00076 case DATA_VARCHAR:
00077 case DATA_VARMYSQL:
00078 case DATA_BINARY:
00079 field->reset();
00080
00081 if (field->type() == DRIZZLE_TYPE_VARCHAR) {
00082
00083
00084
00085
00086 dest = row_mysql_store_true_var_len(
00087 dest, len, flen - field->key_length());
00088 }
00089
00090
00091 memcpy(dest, data, len);
00092 break;
00093
00094 case DATA_BLOB:
00095
00096
00097
00098 row_mysql_store_blob_ref(dest, flen, data, len);
00099 break;
00100
00101 #ifdef UNIV_DEBUG
00102 case DATA_MYSQL:
00103 ut_ad(flen >= len);
00104 ut_ad(DATA_MBMAXLEN(col->mbminmaxlen)
00105 >= DATA_MBMINLEN(col->mbminmaxlen));
00106 ut_ad(DATA_MBMAXLEN(col->mbminmaxlen)
00107 > DATA_MBMINLEN(col->mbminmaxlen) || flen == len);
00108 memcpy(dest, data, len);
00109 break;
00110
00111 default:
00112 case DATA_SYS_CHILD:
00113 case DATA_SYS:
00114
00115 ut_ad(0);
00116
00117 case DATA_CHAR:
00118 case DATA_FIXBINARY:
00119 case DATA_FLOAT:
00120 case DATA_DOUBLE:
00121 case DATA_DECIMAL:
00122
00123 ut_ad(flen == len);
00124 #else
00125 default:
00126 #endif
00127 memcpy(dest, data, len);
00128 }
00129 }
00130
00131
00133 UNIV_INTERN
00134 void
00135 innobase_rec_to_mysql(
00136
00137 Table* table,
00138 const rec_t* rec,
00139 const dict_index_t* index,
00140 const ulint* offsets)
00142 {
00143 uint n_fields = table->getShare()->sizeFields();
00144 uint i;
00145
00146 ut_ad(n_fields == dict_table_get_n_user_cols(index->table));
00147
00148 for (i = 0; i < n_fields; i++) {
00149 Field* field = table->getField(i);
00150 ulint ipos;
00151 ulint ilen;
00152 const unsigned char* ifield;
00153
00154 field->reset();
00155
00156 ipos = dict_index_get_nth_col_pos(index, i);
00157
00158 if (UNIV_UNLIKELY(ipos == ULINT_UNDEFINED)) {
00159 null_field:
00160 field->set_null();
00161 continue;
00162 }
00163
00164 ifield = rec_get_nth_field(rec, offsets, ipos, &ilen);
00165
00166
00167 if (ilen == UNIV_SQL_NULL) {
00168 ut_ad(field->real_maybe_null());
00169 goto null_field;
00170 }
00171
00172 field->set_notnull();
00173
00174 innobase_col_to_mysql(
00175 dict_field_get_col(
00176 dict_index_get_nth_field(index, ipos)),
00177 ifield, ilen, field);
00178 }
00179 }
00180
00181
00183 UNIV_INTERN
00184 void
00185 innobase_rec_reset(
00186
00187 Table* table)
00188 {
00189 uint n_fields = table->getShare()->sizeFields();
00190 uint i;
00191
00192 for (i = 0; i < n_fields; i++) {
00193 table->getField(i)->set_default();
00194 }
00195 }
00196
00197 #if 0 // This is a part of the fast index code.
00198
00200 static
00201 void
00202 innobase_convert_tablename(
00203
00204 char* s)
00205 {
00206
00207 char* slash = strchr(s, '/');
00208
00209 if (slash) {
00210 char* t;
00211
00212 *slash = 0;
00213 strncpy(s, s, slash - s + 1);
00214
00215 t = s + strlen(s);
00216 ut_ad(slash >= t);
00217
00218 *t++ = '.';
00219 slash++;
00220
00221 strncpy(t, slash, slash - t + strlen(slash));
00222 }
00223 }
00224
00225
00226
00229 static
00230 int
00231 innobase_check_index_keys(
00232
00233 const KeyInfo* key_info,
00234 ulint num_of_keys,
00236 const dict_table_t* table)
00237 {
00238 ulint key_num;
00239
00240 ut_ad(key_info);
00241 ut_ad(num_of_keys);
00242
00243 for (key_num = 0; key_num < num_of_keys; key_num++) {
00244 const KeyInfo& key = key_info[key_num];
00245
00246
00247
00248
00249 for (ulint i = 0; i < key_num; i++) {
00250 const KeyInfo& key2 = key_info[i];
00251
00252 if (0 == strcmp(key.name, key2.name)) {
00253 my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0),
00254 key.name);
00255
00256 return(ER_WRONG_NAME_FOR_INDEX);
00257 }
00258 }
00259
00260
00261
00262 for (const dict_index_t* index
00263 = dict_table_get_first_index(table);
00264 index; index = dict_table_get_next_index(index)) {
00265
00266 if (0 == strcmp(key.name, index->name)) {
00267 my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0),
00268 key.name);
00269
00270 return(ER_WRONG_NAME_FOR_INDEX);
00271 }
00272 }
00273
00274
00275
00276
00277
00278 for (ulint i = 0; i < key.key_parts; i++) {
00279 const KeyPartInfo& key_part1
00280 = key.key_part[i];
00281 const Field* field
00282 = key_part1.field;
00283 ibool is_unsigned;
00284
00285 switch (get_innobase_type_from_mysql_type(
00286 &is_unsigned, field)) {
00287 default:
00288 break;
00289 case DATA_INT:
00290 case DATA_FLOAT:
00291 case DATA_DOUBLE:
00292 case DATA_DECIMAL:
00293 if (field->type() == DRIZZLE_TYPE_VARCHAR) {
00294 if (key_part1.length
00295 >= field->pack_length()
00296 - ((Field_varstring*) field)
00297 ->length_bytes) {
00298 break;
00299 }
00300 } else {
00301 if (key_part1.length
00302 >= field->pack_length()) {
00303 break;
00304 }
00305 }
00306
00307 my_error(ER_WRONG_KEY_COLUMN, MYF(0),
00308 field->field_name);
00309 return(ER_WRONG_KEY_COLUMN);
00310 }
00311
00312 for (ulint j = 0; j < i; j++) {
00313 const KeyPartInfo& key_part2
00314 = key.key_part[j];
00315
00316 if (strcmp(key_part1.field->field_name,
00317 key_part2.field->field_name)) {
00318 continue;
00319 }
00320
00321 my_error(ER_WRONG_KEY_COLUMN, MYF(0),
00322 key_part1.field->field_name);
00323 return(ER_WRONG_KEY_COLUMN);
00324 }
00325 }
00326 }
00327
00328 return(0);
00329 }
00330
00331
00333 static
00334 void
00335 innobase_create_index_field_def(
00336
00337 KeyPartInfo* key_part,
00338 mem_heap_t* heap,
00339 merge_index_field_t* index_field)
00341 {
00342 Field* field;
00343 ibool is_unsigned;
00344 ulint col_type;
00345
00346 ut_ad(key_part);
00347 ut_ad(index_field);
00348
00349 field = key_part->field;
00350 ut_a(field);
00351
00352 col_type = get_innobase_type_from_mysql_type(&is_unsigned, field);
00353
00354 if (DATA_BLOB == col_type
00355 || (key_part->length < field->pack_length()
00356 && field->type() != DRIZZLE_TYPE_VARCHAR)
00357 || (field->type() == DRIZZLE_TYPE_VARCHAR
00358 && key_part->length < field->pack_length()
00359 - ((Field_varstring*)field)->length_bytes)) {
00360
00361 index_field->prefix_len = key_part->length;
00362 } else {
00363 index_field->prefix_len = 0;
00364 }
00365
00366 index_field->field_name = mem_heap_strdup(heap, field->field_name);
00367
00368 return;
00369 }
00370
00371
00373 static
00374 void
00375 innobase_create_index_def(
00376
00377 KeyInfo* key,
00378 bool new_primary,
00381 bool key_primary,
00383 merge_index_def_t* index,
00384 mem_heap_t* heap)
00386 {
00387 ulint i;
00388 ulint len;
00389 ulint n_fields = key->key_parts;
00390 char* index_name;
00391
00392 index->fields = (merge_index_field_t*) mem_heap_alloc(
00393 heap, n_fields * sizeof *index->fields);
00394
00395 index->ind_type = 0;
00396 index->n_fields = n_fields;
00397 len = strlen(key->name) + 1;
00398 index->name = index_name = (char*) mem_heap_alloc(heap,
00399 len + !new_primary);
00400
00401 if (UNIV_LIKELY(!new_primary)) {
00402 *index_name++ = TEMP_INDEX_PREFIX;
00403 }
00404
00405 memcpy(index_name, key->name, len);
00406
00407 if (key->flags & HA_NOSAME) {
00408 index->ind_type |= DICT_UNIQUE;
00409 }
00410
00411 if (key_primary) {
00412 index->ind_type |= DICT_CLUSTERED;
00413 }
00414
00415 for (i = 0; i < n_fields; i++) {
00416 innobase_create_index_field_def(&key->key_part[i], heap,
00417 &index->fields[i]);
00418 }
00419
00420 return;
00421 }
00422
00423
00425 static
00426 void
00427 innobase_copy_index_field_def(
00428
00429 const dict_field_t* field,
00430 merge_index_field_t* index_field)
00431 {
00432 assert(field != NULL);
00433 assert(index_field != NULL);
00434
00435 index_field->field_name = field->name;
00436 index_field->prefix_len = field->prefix_len;
00437
00438 return;
00439 }
00440
00441
00443 static
00444 void
00445 innobase_copy_index_def(
00446
00447 const dict_index_t* index,
00448 merge_index_def_t* new_index,
00449 mem_heap_t* heap)
00450 {
00451 ulint n_fields;
00452 ulint i;
00453
00454
00455
00456
00457
00458 n_fields = index->n_user_defined_cols;
00459
00460 new_index->fields = (merge_index_field_t*) mem_heap_alloc(
00461 heap, n_fields * sizeof *new_index->fields);
00462
00463
00464
00465 new_index->ind_type = index->type & ~DICT_CLUSTERED;
00466 new_index->n_fields = n_fields;
00467 new_index->name = index->name;
00468
00469 for (i = 0; i < n_fields; i++) {
00470 innobase_copy_index_field_def(&index->fields[i],
00471 &new_index->fields[i]);
00472 }
00473
00474 return;
00475 }
00476
00477
00495 static
00496 merge_index_def_t*
00497 innobase_create_key_def(
00498
00499 trx_t* trx,
00500 const dict_table_t*table,
00501 mem_heap_t* heap,
00503 KeyInfo* key_info,
00504 ulint& n_keys)
00506 {
00507 ulint i = 0;
00508 merge_index_def_t* indexdef;
00509 merge_index_def_t* indexdefs;
00510 bool new_primary;
00511
00512 indexdef = indexdefs = (merge_index_def_t*)
00513 mem_heap_alloc(heap, sizeof *indexdef
00514 * (n_keys + UT_LIST_GET_LEN(table->indexes)));
00515
00516
00517
00518
00519 new_primary = !my_strcasecmp(system_charset_info,
00520 key_info->name, "PRIMARY");
00521
00522
00523
00524
00525
00526
00527 if (!new_primary && (key_info->flags & HA_NOSAME)
00528 && (!(key_info->flags & HA_KEY_HAS_PART_KEY_SEG))
00529 && row_table_got_default_clust_index(table)) {
00530 uint key_part = key_info->key_parts;
00531
00532 new_primary = TRUE;
00533
00534 while (key_part--) {
00535 if (key_info->key_part[key_part].null_bit == 0) {
00536 new_primary = FALSE;
00537 break;
00538 }
00539 }
00540 }
00541
00542 if (new_primary) {
00543 const dict_index_t* index;
00544
00545
00546 innobase_create_index_def(&key_info[i++], TRUE, TRUE,
00547 indexdef++, heap);
00548
00549 row_mysql_lock_data_dictionary(trx);
00550
00551 index = dict_table_get_first_index(table);
00552
00553
00554
00555
00556
00557
00558 if (dict_index_get_nth_col(index, 0)->mtype == DATA_SYS
00559 || !my_strcasecmp(system_charset_info,
00560 index->name, "PRIMARY")) {
00561 index = dict_table_get_next_index(index);
00562 }
00563
00564 while (index) {
00565 innobase_copy_index_def(index, indexdef++, heap);
00566 index = dict_table_get_next_index(index);
00567 }
00568
00569 row_mysql_unlock_data_dictionary(trx);
00570 }
00571
00572
00573
00574 while (i < n_keys) {
00575 innobase_create_index_def(&key_info[i++], new_primary, FALSE,
00576 indexdef++, heap);
00577 }
00578
00579 n_keys = indexdef - indexdefs;
00580
00581 return(indexdefs);
00582 }
00583
00584
00587 static
00588 char*
00589 innobase_create_temporary_tablename(
00590
00591 mem_heap_t* heap,
00592 char id,
00593 const char* table_name)
00594 {
00595 char* name;
00596 ulint len;
00597 static const char suffix[] = "@0023 ";
00598
00599 len = strlen(table_name);
00600
00601 name = (char*) mem_heap_alloc(heap, len + sizeof suffix);
00602 memcpy(name, table_name, len);
00603 memcpy(name + len, suffix, sizeof suffix);
00604 name[len + (sizeof suffix - 2)] = id;
00605
00606 return(name);
00607 }
00608
00609
00610
00613 UNIV_INTERN
00614 int
00615 ha_innobase::add_index(
00616
00617 Session *session,
00618 Table* i_table,
00619 KeyInfo* key_info,
00620 uint num_of_keys)
00621 {
00622 dict_index_t** index;
00623 dict_table_t* innodb_table;
00624 dict_table_t* indexed_table;
00625 merge_index_def_t* index_defs;
00626 mem_heap_t* heap;
00627 trx_t* trx;
00628 ulint num_of_idx;
00629 ulint num_created = 0;
00630 ibool dict_locked = FALSE;
00631 ulint new_primary;
00632 int error;
00633
00634 ut_a(i_table);
00635 ut_a(key_info);
00636 ut_a(num_of_keys);
00637
00638 if (srv_created_new_raw || srv_force_recovery) {
00639 return(HA_ERR_WRONG_COMMAND);
00640 }
00641
00642 update_session(session);
00643
00644 heap = mem_heap_create(1024);
00645
00646
00647
00648 trx_search_latch_release_if_reserved(prebuilt->trx);
00649 trx_start_if_not_started(prebuilt->trx);
00650
00651
00652
00653 trx = innobase_trx_allocate(user_session);
00654 trx_start_if_not_started(trx);
00655
00656 innodb_table = indexed_table
00657 = dict_table_get(prebuilt->table->name, FALSE);
00658
00659 if (UNIV_UNLIKELY(!innodb_table)) {
00660 error = HA_ERR_NO_SUCH_TABLE;
00661 goto err_exit;
00662 }
00663
00664
00665 if (innobase_index_name_is_reserved(trx, key_info, num_of_keys)) {
00666 error = -1;
00667 } else {
00668
00669 error = innobase_check_index_keys(key_info, num_of_keys,
00670 innodb_table);
00671 }
00672
00673 if (UNIV_UNLIKELY(error)) {
00674 err_exit:
00675 mem_heap_free(heap);
00676 trx_general_rollback_for_mysql(trx, NULL);
00677 trx_free_for_mysql(trx);
00678 trx_commit_for_mysql(prebuilt->trx);
00679 return(error);
00680 }
00681
00682
00683
00684
00685
00686 num_of_idx = num_of_keys;
00687
00688 index_defs = innobase_create_key_def(
00689 trx, innodb_table, heap, key_info, num_of_idx);
00690
00691 new_primary = DICT_CLUSTERED & index_defs[0].ind_type;
00692
00693
00694
00695 index = (dict_index_t**) mem_heap_alloc(
00696 heap, num_of_idx * sizeof *index);
00697
00698
00699
00700 trx_set_dict_operation(trx, TRX_DICT_OP_INDEX);
00701
00702
00703 error = row_merge_lock_table(prebuilt->trx, innodb_table,
00704 new_primary ? LOCK_X : LOCK_S);
00705
00706 if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
00707
00708 goto error_handling;
00709 }
00710
00711
00712
00713
00714 row_mysql_lock_data_dictionary(trx);
00715 dict_locked = TRUE;
00716
00717 ut_d(dict_table_check_for_dup_indexes(innodb_table, FALSE));
00718
00719
00720
00721
00722 if (UNIV_UNLIKELY(new_primary)) {
00723
00724
00725 ut_a(innodb_table->n_mysql_handles_opened == 1);
00726
00727 char* new_table_name = innobase_create_temporary_tablename(
00728 heap, '1', innodb_table->name);
00729
00730
00731 trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
00732 indexed_table = row_merge_create_temporary_table(
00733 new_table_name, index_defs, innodb_table, trx);
00734
00735 if (!indexed_table) {
00736
00737 switch (trx->error_state) {
00738 case DB_TABLESPACE_ALREADY_EXISTS:
00739 case DB_DUPLICATE_KEY:
00740 innobase_convert_tablename(new_table_name);
00741 my_error(HA_ERR_TABLE_EXIST, MYF(0),
00742 new_table_name);
00743 error = HA_ERR_TABLE_EXIST;
00744 break;
00745 default:
00746 error = convert_error_code_to_mysql(
00747 trx->error_state, innodb_table->flags,
00748 user_session);
00749 }
00750
00751 ut_d(dict_table_check_for_dup_indexes(innodb_table,
00752 FALSE));
00753 row_mysql_unlock_data_dictionary(trx);
00754 goto err_exit;
00755 }
00756
00757 trx->table_id = indexed_table->id;
00758 }
00759
00760
00761
00762 for (ulint i = 0; i < num_of_idx; i++) {
00763
00764 index[i] = row_merge_create_index(trx, indexed_table,
00765 &index_defs[i]);
00766
00767 if (!index[i]) {
00768 error = trx->error_state;
00769 goto error_handling;
00770 }
00771
00772 num_created++;
00773 }
00774
00775 ut_ad(error == DB_SUCCESS);
00776
00777
00778
00779 share->idx_trans_tbl.index_count = 0;
00780
00781
00782
00783
00784
00785
00786
00787 trx_commit_for_mysql(trx);
00788
00789 row_mysql_unlock_data_dictionary(trx);
00790 dict_locked = FALSE;
00791
00792 ut_a(trx->n_active_thrs == 0);
00793 ut_a(UT_LIST_GET_LEN(trx->signals) == 0);
00794
00795 if (UNIV_UNLIKELY(new_primary)) {
00796
00797
00798 ut_ad(indexed_table != innodb_table);
00799
00800 error = row_merge_lock_table(prebuilt->trx, indexed_table,
00801 LOCK_X);
00802
00803 if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
00804
00805 goto error_handling;
00806 }
00807 }
00808
00809
00810
00811 error = row_merge_build_indexes(prebuilt->trx,
00812 innodb_table, indexed_table,
00813 index, num_of_idx, i_table);
00814
00815 error_handling:
00816
00817
00818
00819
00820 switch (error) {
00821 const char* old_name;
00822 char* tmp_name;
00823 case DB_SUCCESS:
00824 ut_a(!dict_locked);
00825 row_mysql_lock_data_dictionary(trx);
00826 dict_locked = TRUE;
00827
00828 ut_d(dict_table_check_for_dup_indexes(prebuilt->table, TRUE));
00829
00830 if (!new_primary) {
00831 error = row_merge_rename_indexes(trx, indexed_table);
00832
00833 if (error != DB_SUCCESS) {
00834 row_merge_drop_indexes(trx, indexed_table,
00835 index, num_created);
00836 }
00837
00838 goto convert_error;
00839 }
00840
00841
00842
00843
00844
00845 old_name = innodb_table->name;
00846 tmp_name = innobase_create_temporary_tablename(heap, '2',
00847 old_name);
00848
00849 error = row_merge_rename_tables(innodb_table, indexed_table,
00850 tmp_name, trx);
00851
00852 if (error != DB_SUCCESS) {
00853
00854 row_merge_drop_table(trx, indexed_table);
00855
00856 switch (error) {
00857 case DB_TABLESPACE_ALREADY_EXISTS:
00858 case DB_DUPLICATE_KEY:
00859 innobase_convert_tablename(tmp_name);
00860 my_error(HA_ERR_TABLE_EXIST, MYF(0), tmp_name);
00861 error = HA_ERR_TABLE_EXIST;
00862 break;
00863 default:
00864 goto convert_error;
00865 }
00866 break;
00867 }
00868
00869 trx_commit_for_mysql(prebuilt->trx);
00870 row_prebuilt_free(prebuilt, TRUE);
00871 prebuilt = row_create_prebuilt(indexed_table);
00872
00873 indexed_table->n_mysql_handles_opened++;
00874
00875 error = row_merge_drop_table(trx, innodb_table);
00876 innodb_table = indexed_table;
00877 goto convert_error;
00878
00879 case DB_TOO_BIG_RECORD:
00880 my_error(HA_ERR_TO_BIG_ROW, MYF(0));
00881 goto error;
00882 case DB_PRIMARY_KEY_IS_NULL:
00883 my_error(ER_PRIMARY_CANT_HAVE_NULL, MYF(0));
00884
00885 case DB_DUPLICATE_KEY:
00886 error:
00887 prebuilt->trx->error_info = NULL;
00888
00889 default:
00890 trx->error_state = DB_SUCCESS;
00891
00892 if (new_primary) {
00893 if (indexed_table != innodb_table) {
00894 row_merge_drop_table(trx, indexed_table);
00895 }
00896 } else {
00897 if (!dict_locked) {
00898 row_mysql_lock_data_dictionary(trx);
00899 dict_locked = TRUE;
00900 }
00901
00902 row_merge_drop_indexes(trx, indexed_table,
00903 index, num_created);
00904 }
00905
00906 convert_error:
00907 error = convert_error_code_to_mysql(error,
00908 innodb_table->flags,
00909 user_session);
00910 }
00911
00912 mem_heap_free(heap);
00913 trx_commit_for_mysql(trx);
00914 if (prebuilt->trx) {
00915 trx_commit_for_mysql(prebuilt->trx);
00916 }
00917
00918 if (dict_locked) {
00919 ut_d(dict_table_check_for_dup_indexes(innodb_table, FALSE));
00920 row_mysql_unlock_data_dictionary(trx);
00921 }
00922
00923 trx_free_for_mysql(trx);
00924
00925
00926 srv_active_wake_master_thread();
00927
00928 return(error);
00929 }
00930
00931
00934 UNIV_INTERN
00935 int
00936 ha_innobase::prepare_drop_index(
00937
00938 Session *session,
00939 Table* i_table,
00940 uint* key_num,
00941 uint num_of_keys)
00942 {
00943 trx_t* trx;
00944 int err = 0;
00945 uint n_key;
00946
00947 ut_ad(i_table);
00948 ut_ad(key_num);
00949 ut_ad(num_of_keys);
00950 if (srv_created_new_raw || srv_force_recovery) {
00951 return(HA_ERR_WRONG_COMMAND);
00952 }
00953
00954 update_session(session);
00955
00956 trx_search_latch_release_if_reserved(prebuilt->trx);
00957 trx = prebuilt->trx;
00958
00959
00960
00961 row_mysql_lock_data_dictionary(trx);
00962 ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
00963
00964
00965
00966 {
00967 const dict_index_t* index
00968 = dict_table_get_first_index(prebuilt->table);
00969 do {
00970 ut_a(!index->to_be_dropped);
00971 index = dict_table_get_next_index(index);
00972 } while (index);
00973 }
00974
00975 for (n_key = 0; n_key < num_of_keys; n_key++) {
00976 const KeyInfo* key;
00977 dict_index_t* index;
00978
00979 key = i_table->key_info + key_num[n_key];
00980 index = dict_table_get_index_on_name_and_min_id(
00981 prebuilt->table, key->name);
00982
00983 if (!index) {
00984 errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB could not find key n:o %u "
00985 "with name %s for table %s",
00986 key_num[n_key],
00987 key ? key->name : "NULL",
00988 prebuilt->table->name);
00989
00990 err = HA_ERR_KEY_NOT_FOUND;
00991 goto func_exit;
00992 }
00993
00994
00995
00996
00997
00998
00999 if (dict_index_is_clust(index)) {
01000 my_error(ER_REQUIRES_PRIMARY_KEY, MYF(0));
01001 err = -1;
01002 goto func_exit;
01003 }
01004
01005 index->to_be_dropped = TRUE;
01006 }
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021 if (trx->check_foreigns
01022 && session_sql_command(user_session) != SQLCOM_CREATE_INDEX) {
01023 dict_index_t* index;
01024
01025 for (index = dict_table_get_first_index(prebuilt->table);
01026 index;
01027 index = dict_table_get_next_index(index)) {
01028 dict_foreign_t* foreign;
01029
01030 if (!index->to_be_dropped) {
01031
01032 continue;
01033 }
01034
01035
01036 foreign = dict_table_get_referenced_constraint(
01037 prebuilt->table, index);
01038
01039 if (foreign) {
01040 index_needed:
01041 trx_set_detailed_error(
01042 trx,
01043 "Index needed in foreign key "
01044 "constraint");
01045
01046 trx->error_info = index;
01047
01048 err = HA_ERR_DROP_INDEX_FK;
01049 break;
01050 } else {
01051
01052
01053 foreign = dict_table_get_foreign_constraint(
01054 prebuilt->table, index);
01055
01056 if (foreign) {
01057 ut_a(foreign->foreign_index == index);
01058
01059
01060
01061
01062 if (!dict_foreign_find_equiv_index(
01063 foreign)) {
01064
01065 goto index_needed;
01066 }
01067 }
01068 }
01069 }
01070 } else if (session_sql_command(user_session) == SQLCOM_CREATE_INDEX) {
01071
01072
01073
01074
01075
01076 dict_index_t* index;
01077
01078 for (index = dict_table_get_first_index(prebuilt->table);
01079 index;
01080 index = dict_table_get_next_index(index)) {
01081 dict_foreign_t* foreign;
01082
01083 if (!index->to_be_dropped) {
01084
01085 continue;
01086 }
01087
01088
01089 foreign = dict_table_get_foreign_constraint(
01090 prebuilt->table, index);
01091
01092 if (foreign == NULL) {
01093
01094 continue;
01095 }
01096
01097 ut_a(foreign->foreign_index == index);
01098
01099
01100
01101
01102
01103 if (!dict_foreign_find_equiv_index(foreign)) {
01104 trx_set_detailed_error(
01105 trx,
01106 "Index needed in foreign key "
01107 "constraint");
01108
01109 trx->error_info = foreign->foreign_index;
01110
01111 err = HA_ERR_DROP_INDEX_FK;
01112 break;
01113 }
01114 }
01115 }
01116
01117 func_exit:
01118 if (err) {
01119
01120 dict_index_t* index
01121 = dict_table_get_first_index(prebuilt->table);
01122
01123 do {
01124 index->to_be_dropped = FALSE;
01125 index = dict_table_get_next_index(index);
01126 } while (index);
01127 }
01128
01129 ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
01130 row_mysql_unlock_data_dictionary(trx);
01131
01132 return(err);
01133 }
01134
01135
01138 UNIV_INTERN
01139 int
01140 ha_innobase::final_drop_index(
01141
01142 Session *session,
01143 Table* )
01144 {
01145 dict_index_t* index;
01146 trx_t* trx;
01147 int err;
01148
01149 if (srv_created_new_raw || srv_force_recovery) {
01150 return(HA_ERR_WRONG_COMMAND);
01151 }
01152
01153 update_session(session);
01154
01155 trx_search_latch_release_if_reserved(prebuilt->trx);
01156 trx_start_if_not_started(prebuilt->trx);
01157
01158
01159
01160 trx = innobase_trx_allocate(user_session);
01161 trx_start_if_not_started(trx);
01162
01163
01164
01165 trx_set_dict_operation(trx, TRX_DICT_OP_INDEX);
01166
01167
01168
01169 err = convert_error_code_to_mysql(
01170 row_merge_lock_table(prebuilt->trx, prebuilt->table, LOCK_X),
01171 prebuilt->table->flags, user_session);
01172
01173 row_mysql_lock_data_dictionary(trx);
01174 ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
01175
01176 if (UNIV_UNLIKELY(err)) {
01177
01178
01179 for (index = dict_table_get_first_index(prebuilt->table);
01180 index; index = dict_table_get_next_index(index)) {
01181
01182 index->to_be_dropped = FALSE;
01183 }
01184
01185 goto func_exit;
01186 }
01187
01188
01189
01190 index = dict_table_get_first_index(prebuilt->table);
01191
01192 while (index) {
01193 dict_index_t* next_index;
01194
01195 next_index = dict_table_get_next_index(index);
01196
01197 if (index->to_be_dropped) {
01198
01199 row_merge_drop_index(index, prebuilt->table, trx);
01200 }
01201
01202 index = next_index;
01203 }
01204
01205
01206 for (index = dict_table_get_first_index(prebuilt->table);
01207 index; index = dict_table_get_next_index(index)) {
01208 ut_a(!index->to_be_dropped);
01209 }
01210
01211
01212
01213 share->idx_trans_tbl.index_count = 0;
01214
01215 func_exit:
01216 ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
01217 trx_commit_for_mysql(trx);
01218 trx_commit_for_mysql(prebuilt->trx);
01219 row_mysql_unlock_data_dictionary(trx);
01220
01221
01222
01223
01224
01225 log_buffer_flush_to_disk();
01226
01227 trx_free_for_mysql(trx);
01228
01229
01230
01231
01232 srv_active_wake_master_thread();
01233
01234 return(err);
01235 }
01236 #endif