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.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 = !system_charset_info->strcasecmp(key_info->name, "PRIMARY");
00520
00521
00522
00523
00524
00525
00526 if (!new_primary && (key_info->flags & HA_NOSAME)
00527 && (!(key_info->flags & HA_KEY_HAS_PART_KEY_SEG))
00528 && row_table_got_default_clust_index(table)) {
00529 uint key_part = key_info->key_parts;
00530
00531 new_primary = TRUE;
00532
00533 while (key_part--) {
00534 if (key_info->key_part[key_part].null_bit == 0) {
00535 new_primary = FALSE;
00536 break;
00537 }
00538 }
00539 }
00540
00541 if (new_primary) {
00542 const dict_index_t* index;
00543
00544
00545 innobase_create_index_def(&key_info[i++], TRUE, TRUE,
00546 indexdef++, heap);
00547
00548 row_mysql_lock_data_dictionary(trx);
00549
00550 index = dict_table_get_first_index(table);
00551
00552
00553
00554
00555
00556
00557 if (dict_index_get_nth_col(index, 0)->mtype == DATA_SYS
00558 || !system_charset_info->strcasecmp(index->name, "PRIMARY"))
00559 {
00560 index = dict_table_get_next_index(index);
00561 }
00562
00563 while (index) {
00564 innobase_copy_index_def(index, indexdef++, heap);
00565 index = dict_table_get_next_index(index);
00566 }
00567
00568 row_mysql_unlock_data_dictionary(trx);
00569 }
00570
00571
00572
00573 while (i < n_keys) {
00574 innobase_create_index_def(&key_info[i++], new_primary, FALSE,
00575 indexdef++, heap);
00576 }
00577
00578 n_keys = indexdef - indexdefs;
00579
00580 return(indexdefs);
00581 }
00582
00583
00586 static
00587 char*
00588 innobase_create_temporary_tablename(
00589
00590 mem_heap_t* heap,
00591 char id,
00592 const char* table_name)
00593 {
00594 char* name;
00595 ulint len;
00596 static const char suffix[] = "@0023 ";
00597
00598 len = strlen(table_name);
00599
00600 name = (char*) mem_heap_alloc(heap, len + sizeof suffix);
00601 memcpy(name, table_name, len);
00602 memcpy(name + len, suffix, sizeof suffix);
00603 name[len + (sizeof suffix - 2)] = id;
00604
00605 return(name);
00606 }
00607
00608
00609
00612 UNIV_INTERN
00613 int
00614 ha_innobase::add_index(
00615
00616 Session *session,
00617 Table* i_table,
00618 KeyInfo* key_info,
00619 uint num_of_keys)
00620 {
00621 dict_index_t** index;
00622 dict_table_t* innodb_table;
00623 dict_table_t* indexed_table;
00624 merge_index_def_t* index_defs;
00625 mem_heap_t* heap;
00626 trx_t* trx;
00627 ulint num_of_idx;
00628 ulint num_created = 0;
00629 ibool dict_locked = FALSE;
00630 ulint new_primary;
00631 int error;
00632
00633 ut_a(i_table);
00634 ut_a(key_info);
00635 ut_a(num_of_keys);
00636
00637 if (srv_created_new_raw || srv_force_recovery) {
00638 return(HA_ERR_WRONG_COMMAND);
00639 }
00640
00641 update_session(session);
00642
00643 heap = mem_heap_create(1024);
00644
00645
00646
00647 trx_search_latch_release_if_reserved(prebuilt->trx);
00648 trx_start_if_not_started(prebuilt->trx);
00649
00650
00651
00652 trx = innobase_trx_allocate(user_session);
00653 trx_start_if_not_started(trx);
00654
00655 innodb_table = indexed_table
00656 = dict_table_get(prebuilt->table->name, FALSE);
00657
00658 if (UNIV_UNLIKELY(!innodb_table)) {
00659 error = HA_ERR_NO_SUCH_TABLE;
00660 goto err_exit;
00661 }
00662
00663
00664 if (innobase_index_name_is_reserved(trx, key_info, num_of_keys)) {
00665 error = -1;
00666 } else {
00667
00668 error = innobase_check_index_keys(key_info, num_of_keys,
00669 innodb_table);
00670 }
00671
00672 if (UNIV_UNLIKELY(error)) {
00673 err_exit:
00674 mem_heap_free(heap);
00675 trx_general_rollback_for_mysql(trx, NULL);
00676 trx_free_for_mysql(trx);
00677 trx_commit_for_mysql(prebuilt->trx);
00678 return(error);
00679 }
00680
00681
00682
00683
00684
00685 num_of_idx = num_of_keys;
00686
00687 index_defs = innobase_create_key_def(
00688 trx, innodb_table, heap, key_info, num_of_idx);
00689
00690 new_primary = DICT_CLUSTERED & index_defs[0].ind_type;
00691
00692
00693
00694 index = (dict_index_t**) mem_heap_alloc(
00695 heap, num_of_idx * sizeof *index);
00696
00697
00698
00699 trx_set_dict_operation(trx, TRX_DICT_OP_INDEX);
00700
00701
00702 error = row_merge_lock_table(prebuilt->trx, innodb_table,
00703 new_primary ? LOCK_X : LOCK_S);
00704
00705 if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
00706
00707 goto error_handling;
00708 }
00709
00710
00711
00712
00713 row_mysql_lock_data_dictionary(trx);
00714 dict_locked = TRUE;
00715
00716 ut_d(dict_table_check_for_dup_indexes(innodb_table, FALSE));
00717
00718
00719
00720
00721 if (UNIV_UNLIKELY(new_primary)) {
00722
00723
00724 ut_a(innodb_table->n_mysql_handles_opened == 1);
00725
00726 char* new_table_name = innobase_create_temporary_tablename(
00727 heap, '1', innodb_table->name);
00728
00729
00730 trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
00731 indexed_table = row_merge_create_temporary_table(
00732 new_table_name, index_defs, innodb_table, trx);
00733
00734 if (!indexed_table) {
00735
00736 switch (trx->error_state) {
00737 case DB_TABLESPACE_ALREADY_EXISTS:
00738 case DB_DUPLICATE_KEY:
00739 innobase_convert_tablename(new_table_name);
00740 my_error(HA_ERR_TABLE_EXIST, MYF(0),
00741 new_table_name);
00742 error = HA_ERR_TABLE_EXIST;
00743 break;
00744 default:
00745 error = convert_error_code_to_mysql(
00746 trx->error_state, innodb_table->flags,
00747 user_session);
00748 }
00749
00750 ut_d(dict_table_check_for_dup_indexes(innodb_table,
00751 FALSE));
00752 row_mysql_unlock_data_dictionary(trx);
00753 goto err_exit;
00754 }
00755
00756 trx->table_id = indexed_table->id;
00757 }
00758
00759
00760
00761 for (ulint i = 0; i < num_of_idx; i++) {
00762
00763 index[i] = row_merge_create_index(trx, indexed_table,
00764 &index_defs[i]);
00765
00766 if (!index[i]) {
00767 error = trx->error_state;
00768 goto error_handling;
00769 }
00770
00771 num_created++;
00772 }
00773
00774 ut_ad(error == DB_SUCCESS);
00775
00776
00777
00778 share->idx_trans_tbl.index_count = 0;
00779
00780
00781
00782
00783
00784
00785
00786 trx_commit_for_mysql(trx);
00787
00788 row_mysql_unlock_data_dictionary(trx);
00789 dict_locked = FALSE;
00790
00791 ut_a(trx->n_active_thrs == 0);
00792 ut_a(UT_LIST_GET_LEN(trx->signals) == 0);
00793
00794 if (UNIV_UNLIKELY(new_primary)) {
00795
00796
00797 ut_ad(indexed_table != innodb_table);
00798
00799 error = row_merge_lock_table(prebuilt->trx, indexed_table,
00800 LOCK_X);
00801
00802 if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
00803
00804 goto error_handling;
00805 }
00806 }
00807
00808
00809
00810 error = row_merge_build_indexes(prebuilt->trx,
00811 innodb_table, indexed_table,
00812 index, num_of_idx, i_table);
00813
00814 error_handling:
00815
00816
00817
00818
00819 switch (error) {
00820 const char* old_name;
00821 char* tmp_name;
00822 case DB_SUCCESS:
00823 ut_a(!dict_locked);
00824 row_mysql_lock_data_dictionary(trx);
00825 dict_locked = TRUE;
00826
00827 ut_d(dict_table_check_for_dup_indexes(prebuilt->table, TRUE));
00828
00829 if (!new_primary) {
00830 error = row_merge_rename_indexes(trx, indexed_table);
00831
00832 if (error != DB_SUCCESS) {
00833 row_merge_drop_indexes(trx, indexed_table,
00834 index, num_created);
00835 }
00836
00837 goto convert_error;
00838 }
00839
00840
00841
00842
00843
00844 old_name = innodb_table->name;
00845 tmp_name = innobase_create_temporary_tablename(heap, '2',
00846 old_name);
00847
00848 error = row_merge_rename_tables(innodb_table, indexed_table,
00849 tmp_name, trx);
00850
00851 if (error != DB_SUCCESS) {
00852
00853 row_merge_drop_table(trx, indexed_table);
00854
00855 switch (error) {
00856 case DB_TABLESPACE_ALREADY_EXISTS:
00857 case DB_DUPLICATE_KEY:
00858 innobase_convert_tablename(tmp_name);
00859 my_error(HA_ERR_TABLE_EXIST, MYF(0), tmp_name);
00860 error = HA_ERR_TABLE_EXIST;
00861 break;
00862 default:
00863 goto convert_error;
00864 }
00865 break;
00866 }
00867
00868 trx_commit_for_mysql(prebuilt->trx);
00869 row_prebuilt_free(prebuilt, TRUE);
00870 prebuilt = row_create_prebuilt(indexed_table);
00871
00872 indexed_table->n_mysql_handles_opened++;
00873
00874 error = row_merge_drop_table(trx, innodb_table);
00875 innodb_table = indexed_table;
00876 goto convert_error;
00877
00878 case DB_TOO_BIG_RECORD:
00879 my_error(HA_ERR_TO_BIG_ROW, MYF(0));
00880 goto error;
00881 case DB_PRIMARY_KEY_IS_NULL:
00882 my_error(ER_PRIMARY_CANT_HAVE_NULL, MYF(0));
00883
00884 case DB_DUPLICATE_KEY:
00885 error:
00886 prebuilt->trx->error_info = NULL;
00887
00888 default:
00889 trx->error_state = DB_SUCCESS;
00890
00891 if (new_primary) {
00892 if (indexed_table != innodb_table) {
00893 row_merge_drop_table(trx, indexed_table);
00894 }
00895 } else {
00896 if (!dict_locked) {
00897 row_mysql_lock_data_dictionary(trx);
00898 dict_locked = TRUE;
00899 }
00900
00901 row_merge_drop_indexes(trx, indexed_table,
00902 index, num_created);
00903 }
00904
00905 convert_error:
00906 error = convert_error_code_to_mysql(error,
00907 innodb_table->flags,
00908 user_session);
00909 }
00910
00911 mem_heap_free(heap);
00912 trx_commit_for_mysql(trx);
00913 if (prebuilt->trx) {
00914 trx_commit_for_mysql(prebuilt->trx);
00915 }
00916
00917 if (dict_locked) {
00918 ut_d(dict_table_check_for_dup_indexes(innodb_table, FALSE));
00919 row_mysql_unlock_data_dictionary(trx);
00920 }
00921
00922 trx_free_for_mysql(trx);
00923
00924
00925 srv_active_wake_master_thread();
00926
00927 return(error);
00928 }
00929
00930
00933 UNIV_INTERN
00934 int
00935 ha_innobase::prepare_drop_index(
00936
00937 Session *session,
00938 Table* i_table,
00939 uint* key_num,
00940 uint num_of_keys)
00941 {
00942 trx_t* trx;
00943 int err = 0;
00944 uint n_key;
00945
00946 ut_ad(i_table);
00947 ut_ad(key_num);
00948 ut_ad(num_of_keys);
00949 if (srv_created_new_raw || srv_force_recovery) {
00950 return(HA_ERR_WRONG_COMMAND);
00951 }
00952
00953 update_session(session);
00954
00955 trx_search_latch_release_if_reserved(prebuilt->trx);
00956 trx = prebuilt->trx;
00957
00958
00959
00960 row_mysql_lock_data_dictionary(trx);
00961 ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
00962
00963
00964
00965 {
00966 const dict_index_t* index
00967 = dict_table_get_first_index(prebuilt->table);
00968 do {
00969 ut_a(!index->to_be_dropped);
00970 index = dict_table_get_next_index(index);
00971 } while (index);
00972 }
00973
00974 for (n_key = 0; n_key < num_of_keys; n_key++) {
00975 const KeyInfo* key;
00976 dict_index_t* index;
00977
00978 key = i_table->key_info + key_num[n_key];
00979 index = dict_table_get_index_on_name_and_min_id(
00980 prebuilt->table, key->name);
00981
00982 if (!index) {
00983 errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB could not find key n:o %u "
00984 "with name %s for table %s",
00985 key_num[n_key],
00986 key ? key->name : "NULL",
00987 prebuilt->table->name);
00988
00989 err = HA_ERR_KEY_NOT_FOUND;
00990 goto func_exit;
00991 }
00992
00993
00994
00995
00996
00997
00998 if (dict_index_is_clust(index)) {
00999 my_error(ER_REQUIRES_PRIMARY_KEY, MYF(0));
01000 err = -1;
01001 goto func_exit;
01002 }
01003
01004 index->to_be_dropped = TRUE;
01005 }
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020 if (trx->check_foreigns
01021 && session_sql_command(user_session) != SQLCOM_CREATE_INDEX) {
01022 dict_index_t* index;
01023
01024 for (index = dict_table_get_first_index(prebuilt->table);
01025 index;
01026 index = dict_table_get_next_index(index)) {
01027 dict_foreign_t* foreign;
01028
01029 if (!index->to_be_dropped) {
01030
01031 continue;
01032 }
01033
01034
01035 foreign = dict_table_get_referenced_constraint(
01036 prebuilt->table, index);
01037
01038 if (foreign) {
01039 index_needed:
01040 trx_set_detailed_error(
01041 trx,
01042 "Index needed in foreign key "
01043 "constraint");
01044
01045 trx->error_info = index;
01046
01047 err = HA_ERR_DROP_INDEX_FK;
01048 break;
01049 } else {
01050
01051
01052 foreign = dict_table_get_foreign_constraint(
01053 prebuilt->table, index);
01054
01055 if (foreign) {
01056 ut_a(foreign->foreign_index == index);
01057
01058
01059
01060
01061 if (!dict_foreign_find_equiv_index(
01062 foreign)) {
01063
01064 goto index_needed;
01065 }
01066 }
01067 }
01068 }
01069 } else if (session_sql_command(user_session) == SQLCOM_CREATE_INDEX) {
01070
01071
01072
01073
01074
01075 dict_index_t* index;
01076
01077 for (index = dict_table_get_first_index(prebuilt->table);
01078 index;
01079 index = dict_table_get_next_index(index)) {
01080 dict_foreign_t* foreign;
01081
01082 if (!index->to_be_dropped) {
01083
01084 continue;
01085 }
01086
01087
01088 foreign = dict_table_get_foreign_constraint(
01089 prebuilt->table, index);
01090
01091 if (foreign == NULL) {
01092
01093 continue;
01094 }
01095
01096 ut_a(foreign->foreign_index == index);
01097
01098
01099
01100
01101
01102 if (!dict_foreign_find_equiv_index(foreign)) {
01103 trx_set_detailed_error(
01104 trx,
01105 "Index needed in foreign key "
01106 "constraint");
01107
01108 trx->error_info = foreign->foreign_index;
01109
01110 err = HA_ERR_DROP_INDEX_FK;
01111 break;
01112 }
01113 }
01114 }
01115
01116 func_exit:
01117 if (err) {
01118
01119 dict_index_t* index
01120 = dict_table_get_first_index(prebuilt->table);
01121
01122 do {
01123 index->to_be_dropped = FALSE;
01124 index = dict_table_get_next_index(index);
01125 } while (index);
01126 }
01127
01128 ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
01129 row_mysql_unlock_data_dictionary(trx);
01130
01131 return(err);
01132 }
01133
01134
01137 UNIV_INTERN
01138 int
01139 ha_innobase::final_drop_index(
01140
01141 Session *session,
01142 Table* )
01143 {
01144 dict_index_t* index;
01145 trx_t* trx;
01146 int err;
01147
01148 if (srv_created_new_raw || srv_force_recovery) {
01149 return(HA_ERR_WRONG_COMMAND);
01150 }
01151
01152 update_session(session);
01153
01154 trx_search_latch_release_if_reserved(prebuilt->trx);
01155 trx_start_if_not_started(prebuilt->trx);
01156
01157
01158
01159 trx = innobase_trx_allocate(user_session);
01160 trx_start_if_not_started(trx);
01161
01162
01163
01164 trx_set_dict_operation(trx, TRX_DICT_OP_INDEX);
01165
01166
01167
01168 err = convert_error_code_to_mysql(
01169 row_merge_lock_table(prebuilt->trx, prebuilt->table, LOCK_X),
01170 prebuilt->table->flags, user_session);
01171
01172 row_mysql_lock_data_dictionary(trx);
01173 ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
01174
01175 if (UNIV_UNLIKELY(err)) {
01176
01177
01178 for (index = dict_table_get_first_index(prebuilt->table);
01179 index; index = dict_table_get_next_index(index)) {
01180
01181 index->to_be_dropped = FALSE;
01182 }
01183
01184 goto func_exit;
01185 }
01186
01187
01188
01189 index = dict_table_get_first_index(prebuilt->table);
01190
01191 while (index) {
01192 dict_index_t* next_index;
01193
01194 next_index = dict_table_get_next_index(index);
01195
01196 if (index->to_be_dropped) {
01197
01198 row_merge_drop_index(index, prebuilt->table, trx);
01199 }
01200
01201 index = next_index;
01202 }
01203
01204
01205 for (index = dict_table_get_first_index(prebuilt->table);
01206 index; index = dict_table_get_next_index(index)) {
01207 ut_a(!index->to_be_dropped);
01208 }
01209
01210
01211
01212 share->idx_trans_tbl.index_count = 0;
01213
01214 func_exit:
01215 ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
01216 trx_commit_for_mysql(trx);
01217 trx_commit_for_mysql(prebuilt->trx);
01218 row_mysql_unlock_data_dictionary(trx);
01219
01220
01221
01222
01223
01224 log_buffer_flush_to_disk();
01225
01226 trx_free_for_mysql(trx);
01227
01228
01229
01230
01231 srv_active_wake_master_thread();
01232
01233 return(err);
01234 }
01235 #endif