~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Monty Taylor
  • Date: 2010-06-02 22:35:45 UTC
  • mto: This revision was merged to the branch mainline in revision 1586.
  • Revision ID: mordred@inaugust.com-20100602223545-q8ekf9b40a85nwuf
Rearragned unittests into a single exe because of how we need to link it
(thanks lifeless)
Link with server symbols without needing to build a library.
Added an additional atomics test which tests whatever version of the atomics
lib the running platform would actually use.

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
11
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
12
 
13
13
You should have received a copy of the GNU General Public License along with
14
 
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
15
 
St, Fifth Floor, Boston, MA 02110-1301 USA
 
14
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 
15
Place, Suite 330, Boston, MA 02111-1307 USA
16
16
 
17
17
*****************************************************************************/
18
18
 
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
 
131
129
}
132
130
 
133
131
/*************************************************************//**
134
 
Copies an InnoDB record to table->getInsertRecord(). */
 
132
Copies an InnoDB record to table->record[0]. */
135
133
extern "C" UNIV_INTERN
136
134
void
137
135
innobase_rec_to_mysql(
142
140
        const ulint*            offsets)        /*!< in: rec_get_offsets(
143
141
                                                rec, index, ...) */
144
142
{
145
 
        uint    n_fields        = table->getShare()->sizeFields();
 
143
        uint    n_fields        = table->getShare()->fields;
146
144
        uint    i;
147
145
 
148
146
        ut_ad(n_fields == dict_table_get_n_user_cols(index->table));
149
147
 
150
148
        for (i = 0; i < n_fields; i++) {
151
 
                Field*          field   = table->getField(i);
 
149
                Field*          field   = table->field[i];
152
150
                ulint           ipos;
153
151
                ulint           ilen;
154
152
                const unsigned char*    ifield;
181
179
}
182
180
 
183
181
/*************************************************************//**
184
 
Resets table->getInsertRecord(). */
 
182
Resets table->record[0]. */
185
183
extern "C" UNIV_INTERN
186
184
void
187
185
innobase_rec_reset(
188
186
/*===============*/
189
187
        Table*                  table)          /*!< in/out: MySQL table */
190
188
{
191
 
        uint    n_fields        = table->getShare()->sizeFields();
 
189
        uint    n_fields        = table->getShare()->fields;
192
190
        uint    i;
193
191
 
194
192
        for (i = 0; i < n_fields; i++) {
195
 
                table->getField(i)->set_default();
 
193
                table->field[i]->set_default();
196
194
        }
197
195
}
198
196
 
199
 
#if 0 // This is a part of the fast index code.
200
197
/******************************************************************//**
201
198
Removes the filename encoding of a database and table name. */
202
199
static
224
221
        }
225
222
}
226
223
 
227
 
 
228
224
/*******************************************************************//**
229
225
This function checks that index keys are sensible.
230
226
@return 0 or error number */
233
229
innobase_check_index_keys(
234
230
/*======================*/
235
231
        const KeyInfo*  key_info,       /*!< in: Indexes to be created */
236
 
        ulint           num_of_keys,    /*!< in: Number of indexes to
 
232
        ulint           num_of_keys)    /*!< in: Number of indexes to
237
233
                                        be created */
238
 
        const dict_table_t*     table)  /*!< in: Existing indexes */
239
234
{
240
235
        ulint           key_num;
241
236
 
252
247
                        const KeyInfo&  key2 = key_info[i];
253
248
 
254
249
                        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);
 
250
                                errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: key name `%s` appears"
 
251
                                                " twice in CREATE INDEX\n",
 
252
                                                key.name);
271
253
 
272
254
                                return(ER_WRONG_NAME_FOR_INDEX);
273
255
                        }
275
257
 
276
258
                /* Check that MySQL does not try to create a column
277
259
                prefix index field on an inappropriate data type and
278
 
                that the same column does not appear twice in the index. */
 
260
                that the same colum does not appear twice in the index. */
279
261
 
280
262
                for (ulint i = 0; i < key.key_parts; i++) {
281
263
                        const KeyPartInfo&      key_part1
306
288
                                        }
307
289
                                }
308
290
 
309
 
                                my_error(ER_WRONG_KEY_COLUMN, MYF(0),
310
 
                                         field->field_name);
 
291
                                errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: MySQL is trying to"
 
292
                                                " create a column prefix"
 
293
                                                " index field on an"
 
294
                                                " inappropriate data type."
 
295
                                                " column `%s`,"
 
296
                                                " index `%s`.\n",
 
297
                                                field->field_name,
 
298
                                                key.name);
311
299
                                return(ER_WRONG_KEY_COLUMN);
312
300
                        }
313
301
 
320
308
                                        continue;
321
309
                                }
322
310
 
323
 
                                my_error(ER_WRONG_KEY_COLUMN, MYF(0),
324
 
                                         key_part1.field->field_name);
 
311
                                errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: column `%s`"
 
312
                                                " is not allowed to occur"
 
313
                                                " twice in index `%s`.\n",
 
314
                                                key_part1.field->field_name,
 
315
                                                key.name);
325
316
                                return(ER_WRONG_KEY_COLUMN);
326
317
                        }
327
318
                }
493
484
 
494
485
 
495
486
@return key definitions or NULL */
496
 
 
497
487
static
498
488
merge_index_def_t*
499
489
innobase_create_key_def(
522
512
                                     key_info->name, "PRIMARY");
523
513
 
524
514
        /* 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. */
 
515
        columns, MySQL will treat it as a PRIMARY KEY unless the
 
516
        table already has one. */
528
517
 
529
518
        if (!new_primary && (key_info->flags & HA_NOSAME)
530
 
            && (!(key_info->flags & HA_KEY_HAS_PART_KEY_SEG))
531
519
            && row_table_got_default_clust_index(table)) {
532
 
                uint    key_part = key_info->key_parts;
 
520
                uint    key_part = key_info->key_parts;
533
521
 
534
522
                new_primary = TRUE;
535
523
 
608
596
        return(name);
609
597
}
610
598
 
611
 
 
612
599
/*******************************************************************//**
613
600
Create indexes.
614
601
@return 0 or error number */
616
603
int
617
604
ha_innobase::add_index(
618
605
/*===================*/
619
 
                       Session *session,
620
606
        Table*  i_table,        /*!< in: Table where indexes are created */
621
607
        KeyInfo*        key_info,       /*!< in: Indexes to be created */
622
608
        uint    num_of_keys)    /*!< in: Number of indexes to be created */
631
617
        ulint           num_created     = 0;
632
618
        ibool           dict_locked     = FALSE;
633
619
        ulint           new_primary;
634
 
        int             error;
 
620
        ulint           error;
635
621
 
636
622
        ut_a(i_table);
637
623
        ut_a(key_info);
641
627
                return(HA_ERR_WRONG_COMMAND);
642
628
        }
643
629
 
644
 
        update_session(session);
 
630
        update_session();
645
631
 
646
632
        heap = mem_heap_create(1024);
647
633
 
658
644
        innodb_table = indexed_table
659
645
                = dict_table_get(prebuilt->table->name, FALSE);
660
646
 
661
 
        if (UNIV_UNLIKELY(!innodb_table)) {
662
 
                error = HA_ERR_NO_SUCH_TABLE;
663
 
                goto err_exit;
664
 
        }
 
647
        /* Check that index keys are sensible */
665
648
 
666
 
        /* Check if the index name is reserved. */
667
 
        if (innobase_index_name_is_reserved(trx, key_info, num_of_keys)) {
668
 
                error = -1;
669
 
        } else {
670
 
                /* Check that index keys are sensible */
671
 
                error = innobase_check_index_keys(key_info, num_of_keys,
672
 
                                                  innodb_table);
673
 
        }
 
649
        error = innobase_check_index_keys(key_info, num_of_keys);
674
650
 
675
651
        if (UNIV_UNLIKELY(error)) {
676
652
err_exit:
677
653
                mem_heap_free(heap);
678
 
                trx_general_rollback_for_mysql(trx, NULL);
 
654
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
679
655
                trx_free_for_mysql(trx);
680
656
                trx_commit_for_mysql(prebuilt->trx);
681
657
                return(error);
716
692
        row_mysql_lock_data_dictionary(trx);
717
693
        dict_locked = TRUE;
718
694
 
719
 
        ut_d(dict_table_check_for_dup_indexes(innodb_table, FALSE));
720
 
 
721
695
        /* If a new primary key is defined for the table we need
722
696
        to drop the original table and rebuild all indexes. */
723
697
 
750
724
                                        user_session);
751
725
                        }
752
726
 
753
 
                        ut_d(dict_table_check_for_dup_indexes(innodb_table,
754
 
                                                              FALSE));
755
727
                        row_mysql_unlock_data_dictionary(trx);
756
728
                        goto err_exit;
757
729
                }
776
748
 
777
749
        ut_ad(error == DB_SUCCESS);
778
750
 
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
751
        /* 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. */
 
752
        the table locks on the system tables.  Unfortunately, this
 
753
        means that if MySQL crashes while creating a new primary key
 
754
        inside row_merge_build_indexes(), indexed_table will not be
 
755
        dropped on crash recovery.  Thus, it will become orphaned. */
789
756
        trx_commit_for_mysql(trx);
790
757
 
791
758
        row_mysql_unlock_data_dictionary(trx);
815
782
                                        index, num_of_idx, i_table);
816
783
 
817
784
error_handling:
 
785
#ifdef UNIV_DEBUG
 
786
        /* TODO: At the moment we can't handle the following statement
 
787
        in our debugging code below:
 
788
 
 
789
        alter table t drop index b, add index (b);
 
790
 
 
791
        The fix will have to parse the SQL and note that the index
 
792
        being added has the same name as the the one being dropped and
 
793
        ignore that in the dup index check.*/
 
794
        //dict_table_check_for_dup_indexes(prebuilt->table);
 
795
#endif
818
796
 
819
797
        /* After an error, remove all those index definitions from the
820
798
        dictionary which were defined. */
827
805
                row_mysql_lock_data_dictionary(trx);
828
806
                dict_locked = TRUE;
829
807
 
830
 
                ut_d(dict_table_check_for_dup_indexes(prebuilt->table, TRUE));
831
 
 
832
808
                if (!new_primary) {
833
809
                        error = row_merge_rename_indexes(trx, indexed_table);
834
810
 
875
851
                indexed_table->n_mysql_handles_opened++;
876
852
 
877
853
                error = row_merge_drop_table(trx, innodb_table);
878
 
                innodb_table = indexed_table;
879
854
                goto convert_error;
880
855
 
881
856
        case DB_TOO_BIG_RECORD:
889
864
                prebuilt->trx->error_info = NULL;
890
865
                /* fall through */
891
866
        default:
892
 
                trx->error_state = DB_SUCCESS;
893
 
 
894
867
                if (new_primary) {
895
 
                        if (indexed_table != innodb_table) {
896
 
                                row_merge_drop_table(trx, indexed_table);
897
 
                        }
 
868
                        row_merge_drop_table(trx, indexed_table);
898
869
                } else {
899
870
                        if (!dict_locked) {
900
871
                                row_mysql_lock_data_dictionary(trx);
918
889
        }
919
890
 
920
891
        if (dict_locked) {
921
 
                ut_d(dict_table_check_for_dup_indexes(innodb_table, FALSE));
922
892
                row_mysql_unlock_data_dictionary(trx);
923
893
        }
924
894
 
937
907
int
938
908
ha_innobase::prepare_drop_index(
939
909
/*============================*/
940
 
                                Session *session,
941
910
        Table*  i_table,        /*!< in: Table where indexes are dropped */
942
911
        uint*   key_num,        /*!< in: Key nums to be dropped */
943
912
        uint    num_of_keys)    /*!< in: Number of keys to be dropped */
953
922
                return(HA_ERR_WRONG_COMMAND);
954
923
        }
955
924
 
956
 
        update_session(session);
 
925
        update_session();
957
926
 
958
927
        trx_search_latch_release_if_reserved(prebuilt->trx);
959
928
        trx = prebuilt->trx;
961
930
        /* Test and mark all the indexes to be dropped */
962
931
 
963
932
        row_mysql_lock_data_dictionary(trx);
964
 
        ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
965
933
 
966
934
        /* Check that none of the indexes have previously been flagged
967
935
        for deletion. */
1127
1095
                } while (index);
1128
1096
        }
1129
1097
 
1130
 
        ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
1131
1098
        row_mysql_unlock_data_dictionary(trx);
1132
1099
 
1133
1100
        return(err);
1140
1107
int
1141
1108
ha_innobase::final_drop_index(
1142
1109
/*==========================*/
1143
 
                              Session *session,
1144
1110
        Table*  )               /*!< in: Table where indexes are dropped */
1145
1111
{
1146
1112
        dict_index_t*   index;          /*!< Index to be dropped */
1151
1117
                return(HA_ERR_WRONG_COMMAND);
1152
1118
        }
1153
1119
 
1154
 
        update_session(session);
 
1120
        update_session();
1155
1121
 
1156
1122
        trx_search_latch_release_if_reserved(prebuilt->trx);
1157
1123
        trx_start_if_not_started(prebuilt->trx);
1172
1138
                prebuilt->table->flags, user_session);
1173
1139
 
1174
1140
        row_mysql_lock_data_dictionary(trx);
1175
 
        ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
1176
1141
 
1177
1142
        if (UNIV_UNLIKELY(err)) {
1178
1143
 
1209
1174
                ut_a(!index->to_be_dropped);
1210
1175
        }
1211
1176
 
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;
 
1177
#ifdef UNIV_DEBUG
 
1178
        dict_table_check_for_dup_indexes(prebuilt->table);
 
1179
#endif
1215
1180
 
1216
1181
func_exit:
1217
 
        ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
1218
1182
        trx_commit_for_mysql(trx);
1219
1183
        trx_commit_for_mysql(prebuilt->trx);
1220
1184
        row_mysql_unlock_data_dictionary(trx);
1234
1198
 
1235
1199
        return(err);
1236
1200
}
1237
 
#endif