~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/handler/handler0alter.cc

[patch 112/129] Merge patch for revision 1925 from InnoDB SVN:
revno: 1925
revision-id: svn-v4:16c675df-0fcb-4bc9-8058-dcc011a37293:branches/zip:6169
parent: svn-v4:16c675df-0fcb-4bc9-8058-dcc011a37293:branches/zip:6163
committer: calvin
timestamp: Thu 2009-11-12 12:40:43 +0000
message:
  branches/zip: add test case for bug#46676
  
  This crash is reproducible with InnoDB plugin 1.0.4 + MySQL 5.1.37.
  But no longer reproducible after MySQL 5.1.38 (with plugin 1.0.5).
  Add test case to catch future regression.
added:
  mysql-test/innodb_bug46676.result 6169@16c675df-0fcb-4bc9-8058-dcc011a37293:branches%2Fzip%2Fmysql-test%2Finnodb_bug46676.result
  mysql-test/innodb_bug46676.test 6169@16c675df-0fcb-4bc9-8058-dcc011a37293:branches%2Fzip%2Fmysql-test%2Finnodb_bug46676.test
diff:
=== added file 'mysql-test/innodb_bug46676.result'

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
2
 
3
 
Copyright (c) 2005, 2010, Innobase Oy. All Rights Reserved.
 
3
Copyright (c) 2005, 2009, Innobase Oy. All Rights Reserved.
4
4
 
5
5
This program is free software; you can redistribute it and/or modify it under
6
6
the terms of the GNU General Public License as published by the Free Software
103
103
#ifdef UNIV_DEBUG
104
104
        case DATA_MYSQL:
105
105
                ut_ad(flen >= len);
106
 
                ut_ad(DATA_MBMAXLEN(col->mbminmaxlen)
107
 
                      >= DATA_MBMINLEN(col->mbminmaxlen));
108
 
                ut_ad(DATA_MBMAXLEN(col->mbminmaxlen)
109
 
                      > DATA_MBMINLEN(col->mbminmaxlen) || flen == len);
 
106
                ut_ad(col->mbmaxlen >= col->mbminlen);
 
107
                ut_ad(col->mbmaxlen > col->mbminlen || flen == len);
110
108
                memcpy(dest, data, len);
111
109
                break;
112
110
 
233
231
innobase_check_index_keys(
234
232
/*======================*/
235
233
        const KeyInfo*  key_info,       /*!< in: Indexes to be created */
236
 
        ulint           num_of_keys,    /*!< in: Number of indexes to
 
234
        ulint           num_of_keys)    /*!< in: Number of indexes to
237
235
                                        be created */
238
 
        const dict_table_t*     table)  /*!< in: Existing indexes */
239
236
{
240
237
        ulint           key_num;
241
238
 
252
249
                        const KeyInfo&  key2 = key_info[i];
253
250
 
254
251
                        if (0 == strcmp(key.name, key2.name)) {
255
 
                                my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0),
256
 
                                         key.name);
257
 
 
258
 
                                return(ER_WRONG_NAME_FOR_INDEX);
259
 
                        }
260
 
                }
261
 
 
262
 
                /* Check that the same index name does not already exist. */
263
 
 
264
 
                for (const dict_index_t* index
265
 
                             = dict_table_get_first_index(table);
266
 
                     index; index = dict_table_get_next_index(index)) {
267
 
 
268
 
                        if (0 == strcmp(key.name, index->name)) {
269
 
                                my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0),
270
 
                                         key.name);
 
252
                                errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: key name `%s` appears"
 
253
                                                " twice in CREATE INDEX\n",
 
254
                                                key.name);
271
255
 
272
256
                                return(ER_WRONG_NAME_FOR_INDEX);
273
257
                        }
275
259
 
276
260
                /* Check that MySQL does not try to create a column
277
261
                prefix index field on an inappropriate data type and
278
 
                that the same column does not appear twice in the index. */
 
262
                that the same colum does not appear twice in the index. */
279
263
 
280
264
                for (ulint i = 0; i < key.key_parts; i++) {
281
265
                        const KeyPartInfo&      key_part1
306
290
                                        }
307
291
                                }
308
292
 
309
 
                                my_error(ER_WRONG_KEY_COLUMN, MYF(0),
310
 
                                         field->field_name);
 
293
                                errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: MySQL is trying to"
 
294
                                                " create a column prefix"
 
295
                                                " index field on an"
 
296
                                                " inappropriate data type."
 
297
                                                " column `%s`,"
 
298
                                                " index `%s`.\n",
 
299
                                                field->field_name,
 
300
                                                key.name);
311
301
                                return(ER_WRONG_KEY_COLUMN);
312
302
                        }
313
303
 
320
310
                                        continue;
321
311
                                }
322
312
 
323
 
                                my_error(ER_WRONG_KEY_COLUMN, MYF(0),
324
 
                                         key_part1.field->field_name);
 
313
                                errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: column `%s`"
 
314
                                                " is not allowed to occur"
 
315
                                                " twice in index `%s`.\n",
 
316
                                                key_part1.field->field_name,
 
317
                                                key.name);
325
318
                                return(ER_WRONG_KEY_COLUMN);
326
319
                        }
327
320
                }
522
515
                                     key_info->name, "PRIMARY");
523
516
 
524
517
        /* If there is a UNIQUE INDEX consisting entirely of NOT NULL
525
 
        columns and if the index does not contain column prefix(es)
526
 
        (only prefix/part of the column is indexed), MySQL will treat the
527
 
        index as a PRIMARY KEY unless the table already has one. */
 
518
        columns, MySQL will treat it as a PRIMARY KEY unless the
 
519
        table already has one. */
528
520
 
529
521
        if (!new_primary && (key_info->flags & HA_NOSAME)
530
 
            && (!(key_info->flags & HA_KEY_HAS_PART_KEY_SEG))
531
522
            && row_table_got_default_clust_index(table)) {
532
 
                uint    key_part = key_info->key_parts;
 
523
                uint    key_part = key_info->key_parts;
533
524
 
534
525
                new_primary = TRUE;
535
526
 
658
649
        innodb_table = indexed_table
659
650
                = dict_table_get(prebuilt->table->name, FALSE);
660
651
 
661
 
        if (UNIV_UNLIKELY(!innodb_table)) {
662
 
                error = HA_ERR_NO_SUCH_TABLE;
663
 
                goto err_exit;
664
 
        }
665
 
 
666
652
        /* Check if the index name is reserved. */
667
653
        if (innobase_index_name_is_reserved(trx, key_info, num_of_keys)) {
668
654
                error = -1;
669
655
        } else {
670
656
                /* Check that index keys are sensible */
671
 
                error = innobase_check_index_keys(key_info, num_of_keys,
672
 
                                                  innodb_table);
 
657
                error = innobase_check_index_keys(key_info, num_of_keys);
673
658
        }
674
659
 
675
660
        if (UNIV_UNLIKELY(error)) {
716
701
        row_mysql_lock_data_dictionary(trx);
717
702
        dict_locked = TRUE;
718
703
 
719
 
        ut_d(dict_table_check_for_dup_indexes(innodb_table, FALSE));
720
 
 
721
704
        /* If a new primary key is defined for the table we need
722
705
        to drop the original table and rebuild all indexes. */
723
706
 
750
733
                                        user_session);
751
734
                        }
752
735
 
753
 
                        ut_d(dict_table_check_for_dup_indexes(innodb_table,
754
 
                                                              FALSE));
755
736
                        row_mysql_unlock_data_dictionary(trx);
756
737
                        goto err_exit;
757
738
                }
776
757
 
777
758
        ut_ad(error == DB_SUCCESS);
778
759
 
779
 
        /* We will need to rebuild index translation table. Set
780
 
        valid index entry count in the translation table to zero */
781
 
        share->idx_trans_tbl.index_count = 0;
782
 
 
783
760
        /* Commit the data dictionary transaction in order to release
784
 
        the table locks on the system tables.  This means that if
785
 
        MySQL crashes while creating a new primary key inside
786
 
        row_merge_build_indexes(), indexed_table will not be dropped
787
 
        by trx_rollback_active().  It will have to be recovered or
788
 
        dropped by the database administrator. */
 
761
        the table locks on the system tables.  Unfortunately, this
 
762
        means that if MySQL crashes while creating a new primary key
 
763
        inside row_merge_build_indexes(), indexed_table will not be
 
764
        dropped on crash recovery.  Thus, it will become orphaned. */
789
765
        trx_commit_for_mysql(trx);
790
766
 
791
767
        row_mysql_unlock_data_dictionary(trx);
815
791
                                        index, num_of_idx, i_table);
816
792
 
817
793
error_handling:
 
794
#ifdef UNIV_DEBUG
 
795
        /* TODO: At the moment we can't handle the following statement
 
796
        in our debugging code below:
 
797
 
 
798
        alter table t drop index b, add index (b);
 
799
 
 
800
        The fix will have to parse the SQL and note that the index
 
801
        being added has the same name as the the one being dropped and
 
802
        ignore that in the dup index check.*/
 
803
        //dict_table_check_for_dup_indexes(prebuilt->table);
 
804
#endif
818
805
 
819
806
        /* After an error, remove all those index definitions from the
820
807
        dictionary which were defined. */
827
814
                row_mysql_lock_data_dictionary(trx);
828
815
                dict_locked = TRUE;
829
816
 
830
 
                ut_d(dict_table_check_for_dup_indexes(prebuilt->table, TRUE));
831
 
 
832
817
                if (!new_primary) {
833
818
                        error = row_merge_rename_indexes(trx, indexed_table);
834
819
 
889
874
                prebuilt->trx->error_info = NULL;
890
875
                /* fall through */
891
876
        default:
892
 
                trx->error_state = DB_SUCCESS;
893
 
 
894
877
                if (new_primary) {
895
 
                        if (indexed_table != innodb_table) {
896
 
                                row_merge_drop_table(trx, indexed_table);
897
 
                        }
 
878
                        row_merge_drop_table(trx, indexed_table);
898
879
                } else {
899
880
                        if (!dict_locked) {
900
881
                                row_mysql_lock_data_dictionary(trx);
918
899
        }
919
900
 
920
901
        if (dict_locked) {
921
 
                ut_d(dict_table_check_for_dup_indexes(innodb_table, FALSE));
922
902
                row_mysql_unlock_data_dictionary(trx);
923
903
        }
924
904
 
961
941
        /* Test and mark all the indexes to be dropped */
962
942
 
963
943
        row_mysql_lock_data_dictionary(trx);
964
 
        ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
965
944
 
966
945
        /* Check that none of the indexes have previously been flagged
967
946
        for deletion. */
1127
1106
                } while (index);
1128
1107
        }
1129
1108
 
1130
 
        ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
1131
1109
        row_mysql_unlock_data_dictionary(trx);
1132
1110
 
1133
1111
        return(err);
1172
1150
                prebuilt->table->flags, user_session);
1173
1151
 
1174
1152
        row_mysql_lock_data_dictionary(trx);
1175
 
        ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
1176
1153
 
1177
1154
        if (UNIV_UNLIKELY(err)) {
1178
1155
 
1209
1186
                ut_a(!index->to_be_dropped);
1210
1187
        }
1211
1188
 
1212
 
        /* We will need to rebuild index translation table. Set
1213
 
        valid index entry count in the translation table to zero */
1214
 
        share->idx_trans_tbl.index_count = 0;
 
1189
#ifdef UNIV_DEBUG
 
1190
        dict_table_check_for_dup_indexes(prebuilt->table);
 
1191
#endif
1215
1192
 
1216
1193
func_exit:
1217
 
        ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
1218
1194
        trx_commit_for_mysql(trx);
1219
1195
        trx_commit_for_mysql(prebuilt->trx);
1220
1196
        row_mysql_unlock_data_dictionary(trx);