~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

New merge for TableShare

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
 
21
21
Smart ALTER TABLE
22
22
*******************************************************/
23
23
 
24
 
#include "config.h"
 
24
#include <drizzled/server_includes.h>
25
25
#include <drizzled/error.h>
26
 
#include "drizzled/charset_info.h"
 
26
#include <mystrings/m_ctype.h>
27
27
#include <drizzled/field.h>
28
28
#include <drizzled/table.h>
29
29
#include <drizzled/field/varstring.h>
30
 
#include "drizzled/internal/my_sys.h"
31
30
 
32
31
extern "C" {
33
32
#include "log0log.h"
103
102
#ifdef UNIV_DEBUG
104
103
        case DATA_MYSQL:
105
104
                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);
 
105
                ut_ad(col->mbmaxlen >= col->mbminlen);
 
106
                ut_ad(col->mbmaxlen > col->mbminlen || flen == len);
110
107
                memcpy(dest, data, len);
111
108
                break;
112
109
 
131
128
}
132
129
 
133
130
/*************************************************************//**
134
 
Copies an InnoDB record to table->getInsertRecord(). */
 
131
Copies an InnoDB record to table->record[0]. */
135
132
extern "C" UNIV_INTERN
136
133
void
137
134
innobase_rec_to_mysql(
142
139
        const ulint*            offsets)        /*!< in: rec_get_offsets(
143
140
                                                rec, index, ...) */
144
141
{
145
 
        uint    n_fields        = table->getShare()->sizeFields();
 
142
        uint    n_fields        = table->s->fields;
146
143
        uint    i;
147
144
 
148
145
        ut_ad(n_fields == dict_table_get_n_user_cols(index->table));
149
146
 
150
147
        for (i = 0; i < n_fields; i++) {
151
 
                Field*          field   = table->getField(i);
 
148
                Field*          field   = table->field[i];
152
149
                ulint           ipos;
153
150
                ulint           ilen;
154
151
                const unsigned char*    ifield;
181
178
}
182
179
 
183
180
/*************************************************************//**
184
 
Resets table->getInsertRecord(). */
 
181
Resets table->record[0]. */
185
182
extern "C" UNIV_INTERN
186
183
void
187
184
innobase_rec_reset(
188
185
/*===============*/
189
186
        Table*                  table)          /*!< in/out: MySQL table */
190
187
{
191
 
        uint    n_fields        = table->getShare()->sizeFields();
 
188
        uint    n_fields        = table->s->fields;
192
189
        uint    i;
193
190
 
194
191
        for (i = 0; i < n_fields; i++) {
195
 
                table->getField(i)->set_default();
 
192
                table->field[i]->set_default();
196
193
        }
197
194
}
198
195
 
199
 
#if 0 // This is a part of the fast index code.
200
196
/******************************************************************//**
201
197
Removes the filename encoding of a database and table name. */
202
198
static
224
220
        }
225
221
}
226
222
 
227
 
 
228
223
/*******************************************************************//**
229
224
This function checks that index keys are sensible.
230
225
@return 0 or error number */
232
227
int
233
228
innobase_check_index_keys(
234
229
/*======================*/
235
 
        const KeyInfo*  key_info,       /*!< in: Indexes to be created */
236
 
        ulint           num_of_keys,    /*!< in: Number of indexes to
 
230
        const KEY*      key_info,       /*!< in: Indexes to be created */
 
231
        ulint           num_of_keys)    /*!< in: Number of indexes to
237
232
                                        be created */
238
 
        const dict_table_t*     table)  /*!< in: Existing indexes */
239
233
{
240
234
        ulint           key_num;
241
235
 
243
237
        ut_ad(num_of_keys);
244
238
 
245
239
        for (key_num = 0; key_num < num_of_keys; key_num++) {
246
 
                const KeyInfo&  key = key_info[key_num];
 
240
                const KEY&      key = key_info[key_num];
247
241
 
248
242
                /* Check that the same index name does not appear
249
243
                twice in indexes to be created. */
250
244
 
251
245
                for (ulint i = 0; i < key_num; i++) {
252
 
                        const KeyInfo&  key2 = key_info[i];
 
246
                        const KEY&      key2 = key_info[i];
253
247
 
254
248
                        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);
 
249
                                errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: key name `%s` appears"
 
250
                                                " twice in CREATE INDEX\n",
 
251
                                                key.name);
271
252
 
272
253
                                return(ER_WRONG_NAME_FOR_INDEX);
273
254
                        }
275
256
 
276
257
                /* Check that MySQL does not try to create a column
277
258
                prefix index field on an inappropriate data type and
278
 
                that the same column does not appear twice in the index. */
 
259
                that the same colum does not appear twice in the index. */
279
260
 
280
261
                for (ulint i = 0; i < key.key_parts; i++) {
281
 
                        const KeyPartInfo&      key_part1
 
262
                        const KEY_PART_INFO&    key_part1
282
263
                                = key.key_part[i];
283
264
                        const Field*            field
284
265
                                = key_part1.field;
306
287
                                        }
307
288
                                }
308
289
 
309
 
                                my_error(ER_WRONG_KEY_COLUMN, MYF(0),
310
 
                                         field->field_name);
 
290
                                errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: MySQL is trying to"
 
291
                                                " create a column prefix"
 
292
                                                " index field on an"
 
293
                                                " inappropriate data type."
 
294
                                                " column `%s`,"
 
295
                                                " index `%s`.\n",
 
296
                                                field->field_name,
 
297
                                                key.name);
311
298
                                return(ER_WRONG_KEY_COLUMN);
312
299
                        }
313
300
 
314
301
                        for (ulint j = 0; j < i; j++) {
315
 
                                const KeyPartInfo&      key_part2
 
302
                                const KEY_PART_INFO&    key_part2
316
303
                                        = key.key_part[j];
317
304
 
318
305
                                if (strcmp(key_part1.field->field_name,
320
307
                                        continue;
321
308
                                }
322
309
 
323
 
                                my_error(ER_WRONG_KEY_COLUMN, MYF(0),
324
 
                                         key_part1.field->field_name);
 
310
                                errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: column `%s`"
 
311
                                                " is not allowed to occur"
 
312
                                                " twice in index `%s`.\n",
 
313
                                                key_part1.field->field_name,
 
314
                                                key.name);
325
315
                                return(ER_WRONG_KEY_COLUMN);
326
316
                        }
327
317
                }
336
326
void
337
327
innobase_create_index_field_def(
338
328
/*============================*/
339
 
        KeyPartInfo*            key_part,       /*!< in: MySQL key definition */
 
329
        KEY_PART_INFO*          key_part,       /*!< in: MySQL key definition */
340
330
        mem_heap_t*             heap,           /*!< in: memory heap */
341
331
        merge_index_field_t*    index_field)    /*!< out: index field
342
332
                                                definition for key_part */
376
366
void
377
367
innobase_create_index_def(
378
368
/*======================*/
379
 
        KeyInfo*                        key,            /*!< in: key definition */
 
369
        KEY*                    key,            /*!< in: key definition */
380
370
        bool                    new_primary,    /*!< in: TRUE=generating
381
371
                                                a new primary key
382
372
                                                on the table */
493
483
 
494
484
 
495
485
@return key definitions or NULL */
496
 
 
497
486
static
498
487
merge_index_def_t*
499
488
innobase_create_key_def(
502
491
        const dict_table_t*table,               /*!< in: table definition */
503
492
        mem_heap_t*     heap,           /*!< in: heap where space for key
504
493
                                        definitions are allocated */
505
 
        KeyInfo*                key_info,       /*!< in: Indexes to be created */
 
494
        KEY*            key_info,       /*!< in: Indexes to be created */
506
495
        ulint&          n_keys)         /*!< in/out: Number of indexes to
507
496
                                        be created */
508
497
{
522
511
                                     key_info->name, "PRIMARY");
523
512
 
524
513
        /* 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. */
 
514
        columns, MySQL will treat it as a PRIMARY KEY unless the
 
515
        table already has one. */
528
516
 
529
517
        if (!new_primary && (key_info->flags & HA_NOSAME)
530
 
            && (!(key_info->flags & HA_KEY_HAS_PART_KEY_SEG))
531
518
            && row_table_got_default_clust_index(table)) {
532
 
                uint    key_part = key_info->key_parts;
 
519
                uint    key_part = key_info->key_parts;
533
520
 
534
521
                new_primary = TRUE;
535
522
 
608
595
        return(name);
609
596
}
610
597
 
611
 
 
612
598
/*******************************************************************//**
613
599
Create indexes.
614
600
@return 0 or error number */
616
602
int
617
603
ha_innobase::add_index(
618
604
/*===================*/
619
 
                       Session *session,
620
605
        Table*  i_table,        /*!< in: Table where indexes are created */
621
 
        KeyInfo*        key_info,       /*!< in: Indexes to be created */
 
606
        KEY*    key_info,       /*!< in: Indexes to be created */
622
607
        uint    num_of_keys)    /*!< in: Number of indexes to be created */
623
608
{
624
609
        dict_index_t**  index;          /*!< Index to be created */
631
616
        ulint           num_created     = 0;
632
617
        ibool           dict_locked     = FALSE;
633
618
        ulint           new_primary;
634
 
        int             error;
 
619
        ulint           error;
635
620
 
636
621
        ut_a(i_table);
637
622
        ut_a(key_info);
641
626
                return(HA_ERR_WRONG_COMMAND);
642
627
        }
643
628
 
644
 
        update_session(session);
 
629
        update_session();
645
630
 
646
631
        heap = mem_heap_create(1024);
647
632
 
658
643
        innodb_table = indexed_table
659
644
                = dict_table_get(prebuilt->table->name, FALSE);
660
645
 
661
 
        if (UNIV_UNLIKELY(!innodb_table)) {
662
 
                error = HA_ERR_NO_SUCH_TABLE;
663
 
                goto err_exit;
664
 
        }
 
646
        /* Check that index keys are sensible */
665
647
 
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
 
        }
 
648
        error = innobase_check_index_keys(key_info, num_of_keys);
674
649
 
675
650
        if (UNIV_UNLIKELY(error)) {
676
651
err_exit:
677
652
                mem_heap_free(heap);
678
 
                trx_general_rollback_for_mysql(trx, NULL);
 
653
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
679
654
                trx_free_for_mysql(trx);
680
655
                trx_commit_for_mysql(prebuilt->trx);
681
656
                return(error);
716
691
        row_mysql_lock_data_dictionary(trx);
717
692
        dict_locked = TRUE;
718
693
 
719
 
        ut_d(dict_table_check_for_dup_indexes(innodb_table, FALSE));
720
 
 
721
694
        /* If a new primary key is defined for the table we need
722
695
        to drop the original table and rebuild all indexes. */
723
696
 
750
723
                                        user_session);
751
724
                        }
752
725
 
753
 
                        ut_d(dict_table_check_for_dup_indexes(innodb_table,
754
 
                                                              FALSE));
755
726
                        row_mysql_unlock_data_dictionary(trx);
756
727
                        goto err_exit;
757
728
                }
776
747
 
777
748
        ut_ad(error == DB_SUCCESS);
778
749
 
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
750
        /* 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. */
 
751
        the table locks on the system tables.  Unfortunately, this
 
752
        means that if MySQL crashes while creating a new primary key
 
753
        inside row_merge_build_indexes(), indexed_table will not be
 
754
        dropped on crash recovery.  Thus, it will become orphaned. */
789
755
        trx_commit_for_mysql(trx);
790
756
 
791
757
        row_mysql_unlock_data_dictionary(trx);
815
781
                                        index, num_of_idx, i_table);
816
782
 
817
783
error_handling:
 
784
#ifdef UNIV_DEBUG
 
785
        /* TODO: At the moment we can't handle the following statement
 
786
        in our debugging code below:
 
787
 
 
788
        alter table t drop index b, add index (b);
 
789
 
 
790
        The fix will have to parse the SQL and note that the index
 
791
        being added has the same name as the the one being dropped and
 
792
        ignore that in the dup index check.*/
 
793
        //dict_table_check_for_dup_indexes(prebuilt->table);
 
794
#endif
818
795
 
819
796
        /* After an error, remove all those index definitions from the
820
797
        dictionary which were defined. */
827
804
                row_mysql_lock_data_dictionary(trx);
828
805
                dict_locked = TRUE;
829
806
 
830
 
                ut_d(dict_table_check_for_dup_indexes(prebuilt->table, TRUE));
831
 
 
832
807
                if (!new_primary) {
833
808
                        error = row_merge_rename_indexes(trx, indexed_table);
834
809
 
875
850
                indexed_table->n_mysql_handles_opened++;
876
851
 
877
852
                error = row_merge_drop_table(trx, innodb_table);
878
 
                innodb_table = indexed_table;
879
853
                goto convert_error;
880
854
 
881
855
        case DB_TOO_BIG_RECORD:
889
863
                prebuilt->trx->error_info = NULL;
890
864
                /* fall through */
891
865
        default:
892
 
                trx->error_state = DB_SUCCESS;
893
 
 
894
866
                if (new_primary) {
895
 
                        if (indexed_table != innodb_table) {
896
 
                                row_merge_drop_table(trx, indexed_table);
897
 
                        }
 
867
                        row_merge_drop_table(trx, indexed_table);
898
868
                } else {
899
869
                        if (!dict_locked) {
900
870
                                row_mysql_lock_data_dictionary(trx);
918
888
        }
919
889
 
920
890
        if (dict_locked) {
921
 
                ut_d(dict_table_check_for_dup_indexes(innodb_table, FALSE));
922
891
                row_mysql_unlock_data_dictionary(trx);
923
892
        }
924
893
 
937
906
int
938
907
ha_innobase::prepare_drop_index(
939
908
/*============================*/
940
 
                                Session *session,
941
909
        Table*  i_table,        /*!< in: Table where indexes are dropped */
942
910
        uint*   key_num,        /*!< in: Key nums to be dropped */
943
911
        uint    num_of_keys)    /*!< in: Number of keys to be dropped */
953
921
                return(HA_ERR_WRONG_COMMAND);
954
922
        }
955
923
 
956
 
        update_session(session);
 
924
        update_session();
957
925
 
958
926
        trx_search_latch_release_if_reserved(prebuilt->trx);
959
927
        trx = prebuilt->trx;
961
929
        /* Test and mark all the indexes to be dropped */
962
930
 
963
931
        row_mysql_lock_data_dictionary(trx);
964
 
        ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
965
932
 
966
933
        /* Check that none of the indexes have previously been flagged
967
934
        for deletion. */
975
942
        }
976
943
 
977
944
        for (n_key = 0; n_key < num_of_keys; n_key++) {
978
 
                const KeyInfo*  key;
 
945
                const KEY*      key;
979
946
                dict_index_t*   index;
980
947
 
981
948
                key = i_table->key_info + key_num[n_key];
1127
1094
                } while (index);
1128
1095
        }
1129
1096
 
1130
 
        ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
1131
1097
        row_mysql_unlock_data_dictionary(trx);
1132
1098
 
1133
1099
        return(err);
1140
1106
int
1141
1107
ha_innobase::final_drop_index(
1142
1108
/*==========================*/
1143
 
                              Session *session,
1144
1109
        Table*  )               /*!< in: Table where indexes are dropped */
1145
1110
{
1146
1111
        dict_index_t*   index;          /*!< Index to be dropped */
1151
1116
                return(HA_ERR_WRONG_COMMAND);
1152
1117
        }
1153
1118
 
1154
 
        update_session(session);
 
1119
        update_session();
1155
1120
 
1156
1121
        trx_search_latch_release_if_reserved(prebuilt->trx);
1157
1122
        trx_start_if_not_started(prebuilt->trx);
1172
1137
                prebuilt->table->flags, user_session);
1173
1138
 
1174
1139
        row_mysql_lock_data_dictionary(trx);
1175
 
        ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
1176
1140
 
1177
1141
        if (UNIV_UNLIKELY(err)) {
1178
1142
 
1209
1173
                ut_a(!index->to_be_dropped);
1210
1174
        }
1211
1175
 
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;
 
1176
#ifdef UNIV_DEBUG
 
1177
        dict_table_check_for_dup_indexes(prebuilt->table);
 
1178
#endif
1215
1179
 
1216
1180
func_exit:
1217
 
        ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
1218
1181
        trx_commit_for_mysql(trx);
1219
1182
        trx_commit_for_mysql(prebuilt->trx);
1220
1183
        row_mysql_unlock_data_dictionary(trx);
1234
1197
 
1235
1198
        return(err);
1236
1199
}
1237
 
#endif