~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Monty Taylor
  • Date: 2009-12-25 08:50:15 UTC
  • mto: This revision was merged to the branch mainline in revision 1255.
  • Revision ID: mordred@inaugust.com-20091225085015-83sux5qsvy312gew
MEM_ROOT == memory::Root

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
 
28
28
#include <drizzled/table.h>
29
29
#include <drizzled/field/varstring.h>
30
30
#include "drizzled/internal/my_sys.h"
 
31
#include "drizzled/my_error.h"
31
32
 
 
33
extern "C" {
32
34
#include "log0log.h"
33
35
#include "row0merge.h"
34
36
#include "srv0srv.h"
36
38
#include "trx0roll.h"
37
39
#include "ha_prototypes.h"
38
40
#include "handler0alter.h"
 
41
}
39
42
 
40
43
#include "ha_innodb.h"
41
44
#include "handler0vars.h"
101
104
#ifdef UNIV_DEBUG
102
105
        case DATA_MYSQL:
103
106
                ut_ad(flen >= len);
104
 
                ut_ad(DATA_MBMAXLEN(col->mbminmaxlen)
105
 
                      >= DATA_MBMINLEN(col->mbminmaxlen));
106
 
                ut_ad(DATA_MBMAXLEN(col->mbminmaxlen)
107
 
                      > DATA_MBMINLEN(col->mbminmaxlen) || flen == len);
 
107
                ut_ad(col->mbmaxlen >= col->mbminlen);
 
108
                ut_ad(col->mbmaxlen > col->mbminlen || flen == len);
108
109
                memcpy(dest, data, len);
109
110
                break;
110
111
 
129
130
}
130
131
 
131
132
/*************************************************************//**
132
 
Copies an InnoDB record to table->getInsertRecord(). */
133
 
UNIV_INTERN
 
133
Copies an InnoDB record to table->record[0]. */
 
134
extern "C" UNIV_INTERN
134
135
void
135
136
innobase_rec_to_mysql(
136
137
/*==================*/
140
141
        const ulint*            offsets)        /*!< in: rec_get_offsets(
141
142
                                                rec, index, ...) */
142
143
{
143
 
        uint    n_fields        = table->getShare()->sizeFields();
 
144
        uint    n_fields        = table->s->fields;
144
145
        uint    i;
145
146
 
146
147
        ut_ad(n_fields == dict_table_get_n_user_cols(index->table));
147
148
 
148
149
        for (i = 0; i < n_fields; i++) {
149
 
                Field*          field   = table->getField(i);
 
150
                Field*          field   = table->field[i];
150
151
                ulint           ipos;
151
152
                ulint           ilen;
152
153
                const unsigned char*    ifield;
179
180
}
180
181
 
181
182
/*************************************************************//**
182
 
Resets table->getInsertRecord(). */
183
 
UNIV_INTERN
 
183
Resets table->record[0]. */
 
184
extern "C" UNIV_INTERN
184
185
void
185
186
innobase_rec_reset(
186
187
/*===============*/
187
188
        Table*                  table)          /*!< in/out: MySQL table */
188
189
{
189
 
        uint    n_fields        = table->getShare()->sizeFields();
 
190
        uint    n_fields        = table->s->fields;
190
191
        uint    i;
191
192
 
192
193
        for (i = 0; i < n_fields; i++) {
193
 
                table->getField(i)->set_default();
 
194
                table->field[i]->set_default();
194
195
        }
195
196
}
196
197
 
197
 
#if 0 // This is a part of the fast index code.
198
198
/******************************************************************//**
199
199
Removes the filename encoding of a database and table name. */
200
200
static
222
222
        }
223
223
}
224
224
 
225
 
 
226
225
/*******************************************************************//**
227
226
This function checks that index keys are sensible.
228
227
@return 0 or error number */
230
229
int
231
230
innobase_check_index_keys(
232
231
/*======================*/
233
 
        const KeyInfo*  key_info,       /*!< in: Indexes to be created */
234
 
        ulint           num_of_keys,    /*!< in: Number of indexes to
 
232
        const KEY*      key_info,       /*!< in: Indexes to be created */
 
233
        ulint           num_of_keys)    /*!< in: Number of indexes to
235
234
                                        be created */
236
 
        const dict_table_t*     table)  /*!< in: Existing indexes */
237
235
{
238
236
        ulint           key_num;
239
237
 
241
239
        ut_ad(num_of_keys);
242
240
 
243
241
        for (key_num = 0; key_num < num_of_keys; key_num++) {
244
 
                const KeyInfo&  key = key_info[key_num];
 
242
                const KEY&      key = key_info[key_num];
245
243
 
246
244
                /* Check that the same index name does not appear
247
245
                twice in indexes to be created. */
248
246
 
249
247
                for (ulint i = 0; i < key_num; i++) {
250
 
                        const KeyInfo&  key2 = key_info[i];
 
248
                        const KEY&      key2 = key_info[i];
251
249
 
252
250
                        if (0 == strcmp(key.name, key2.name)) {
253
 
                                my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0),
254
 
                                         key.name);
255
 
 
256
 
                                return(ER_WRONG_NAME_FOR_INDEX);
257
 
                        }
258
 
                }
259
 
 
260
 
                /* Check that the same index name does not already exist. */
261
 
 
262
 
                for (const dict_index_t* index
263
 
                             = dict_table_get_first_index(table);
264
 
                     index; index = dict_table_get_next_index(index)) {
265
 
 
266
 
                        if (0 == strcmp(key.name, index->name)) {
267
 
                                my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0),
268
 
                                         key.name);
 
251
                                errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: key name `%s` appears"
 
252
                                                " twice in CREATE INDEX\n",
 
253
                                                key.name);
269
254
 
270
255
                                return(ER_WRONG_NAME_FOR_INDEX);
271
256
                        }
273
258
 
274
259
                /* Check that MySQL does not try to create a column
275
260
                prefix index field on an inappropriate data type and
276
 
                that the same column does not appear twice in the index. */
 
261
                that the same colum does not appear twice in the index. */
277
262
 
278
263
                for (ulint i = 0; i < key.key_parts; i++) {
279
 
                        const KeyPartInfo&      key_part1
 
264
                        const KEY_PART_INFO&    key_part1
280
265
                                = key.key_part[i];
281
266
                        const Field*            field
282
267
                                = key_part1.field;
304
289
                                        }
305
290
                                }
306
291
 
307
 
                                my_error(ER_WRONG_KEY_COLUMN, MYF(0),
308
 
                                         field->field_name);
 
292
                                errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: MySQL is trying to"
 
293
                                                " create a column prefix"
 
294
                                                " index field on an"
 
295
                                                " inappropriate data type."
 
296
                                                " column `%s`,"
 
297
                                                " index `%s`.\n",
 
298
                                                field->field_name,
 
299
                                                key.name);
309
300
                                return(ER_WRONG_KEY_COLUMN);
310
301
                        }
311
302
 
312
303
                        for (ulint j = 0; j < i; j++) {
313
 
                                const KeyPartInfo&      key_part2
 
304
                                const KEY_PART_INFO&    key_part2
314
305
                                        = key.key_part[j];
315
306
 
316
307
                                if (strcmp(key_part1.field->field_name,
318
309
                                        continue;
319
310
                                }
320
311
 
321
 
                                my_error(ER_WRONG_KEY_COLUMN, MYF(0),
322
 
                                         key_part1.field->field_name);
 
312
                                errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: column `%s`"
 
313
                                                " is not allowed to occur"
 
314
                                                " twice in index `%s`.\n",
 
315
                                                key_part1.field->field_name,
 
316
                                                key.name);
323
317
                                return(ER_WRONG_KEY_COLUMN);
324
318
                        }
325
319
                }
334
328
void
335
329
innobase_create_index_field_def(
336
330
/*============================*/
337
 
        KeyPartInfo*            key_part,       /*!< in: MySQL key definition */
 
331
        KEY_PART_INFO*          key_part,       /*!< in: MySQL key definition */
338
332
        mem_heap_t*             heap,           /*!< in: memory heap */
339
333
        merge_index_field_t*    index_field)    /*!< out: index field
340
334
                                                definition for key_part */
374
368
void
375
369
innobase_create_index_def(
376
370
/*======================*/
377
 
        KeyInfo*                        key,            /*!< in: key definition */
 
371
        KEY*                    key,            /*!< in: key definition */
378
372
        bool                    new_primary,    /*!< in: TRUE=generating
379
373
                                                a new primary key
380
374
                                                on the table */
491
485
 
492
486
 
493
487
@return key definitions or NULL */
494
 
 
495
488
static
496
489
merge_index_def_t*
497
490
innobase_create_key_def(
500
493
        const dict_table_t*table,               /*!< in: table definition */
501
494
        mem_heap_t*     heap,           /*!< in: heap where space for key
502
495
                                        definitions are allocated */
503
 
        KeyInfo*                key_info,       /*!< in: Indexes to be created */
 
496
        KEY*            key_info,       /*!< in: Indexes to be created */
504
497
        ulint&          n_keys)         /*!< in/out: Number of indexes to
505
498
                                        be created */
506
499
{
520
513
                                     key_info->name, "PRIMARY");
521
514
 
522
515
        /* If there is a UNIQUE INDEX consisting entirely of NOT NULL
523
 
        columns and if the index does not contain column prefix(es)
524
 
        (only prefix/part of the column is indexed), MySQL will treat the
525
 
        index as a PRIMARY KEY unless the table already has one. */
 
516
        columns, MySQL will treat it as a PRIMARY KEY unless the
 
517
        table already has one. */
526
518
 
527
519
        if (!new_primary && (key_info->flags & HA_NOSAME)
528
 
            && (!(key_info->flags & HA_KEY_HAS_PART_KEY_SEG))
529
520
            && row_table_got_default_clust_index(table)) {
530
 
                uint    key_part = key_info->key_parts;
 
521
                uint    key_part = key_info->key_parts;
531
522
 
532
523
                new_primary = TRUE;
533
524
 
606
597
        return(name);
607
598
}
608
599
 
609
 
 
610
600
/*******************************************************************//**
611
601
Create indexes.
612
602
@return 0 or error number */
614
604
int
615
605
ha_innobase::add_index(
616
606
/*===================*/
617
 
                       Session *session,
618
607
        Table*  i_table,        /*!< in: Table where indexes are created */
619
 
        KeyInfo*        key_info,       /*!< in: Indexes to be created */
 
608
        KEY*    key_info,       /*!< in: Indexes to be created */
620
609
        uint    num_of_keys)    /*!< in: Number of indexes to be created */
621
610
{
622
611
        dict_index_t**  index;          /*!< Index to be created */
629
618
        ulint           num_created     = 0;
630
619
        ibool           dict_locked     = FALSE;
631
620
        ulint           new_primary;
632
 
        int             error;
 
621
        ulint           error;
633
622
 
634
623
        ut_a(i_table);
635
624
        ut_a(key_info);
639
628
                return(HA_ERR_WRONG_COMMAND);
640
629
        }
641
630
 
642
 
        update_session(session);
 
631
        update_session();
643
632
 
644
633
        heap = mem_heap_create(1024);
645
634
 
656
645
        innodb_table = indexed_table
657
646
                = dict_table_get(prebuilt->table->name, FALSE);
658
647
 
659
 
        if (UNIV_UNLIKELY(!innodb_table)) {
660
 
                error = HA_ERR_NO_SUCH_TABLE;
661
 
                goto err_exit;
662
 
        }
 
648
        /* Check that index keys are sensible */
663
649
 
664
 
        /* Check if the index name is reserved. */
665
 
        if (innobase_index_name_is_reserved(trx, key_info, num_of_keys)) {
666
 
                error = -1;
667
 
        } else {
668
 
                /* Check that index keys are sensible */
669
 
                error = innobase_check_index_keys(key_info, num_of_keys,
670
 
                                                  innodb_table);
671
 
        }
 
650
        error = innobase_check_index_keys(key_info, num_of_keys);
672
651
 
673
652
        if (UNIV_UNLIKELY(error)) {
674
653
err_exit:
675
654
                mem_heap_free(heap);
676
 
                trx_general_rollback_for_mysql(trx, NULL);
 
655
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
677
656
                trx_free_for_mysql(trx);
678
657
                trx_commit_for_mysql(prebuilt->trx);
679
658
                return(error);
714
693
        row_mysql_lock_data_dictionary(trx);
715
694
        dict_locked = TRUE;
716
695
 
717
 
        ut_d(dict_table_check_for_dup_indexes(innodb_table, FALSE));
718
 
 
719
696
        /* If a new primary key is defined for the table we need
720
697
        to drop the original table and rebuild all indexes. */
721
698
 
748
725
                                        user_session);
749
726
                        }
750
727
 
751
 
                        ut_d(dict_table_check_for_dup_indexes(innodb_table,
752
 
                                                              FALSE));
753
728
                        row_mysql_unlock_data_dictionary(trx);
754
729
                        goto err_exit;
755
730
                }
774
749
 
775
750
        ut_ad(error == DB_SUCCESS);
776
751
 
777
 
        /* We will need to rebuild index translation table. Set
778
 
        valid index entry count in the translation table to zero */
779
 
        share->idx_trans_tbl.index_count = 0;
780
 
 
781
752
        /* Commit the data dictionary transaction in order to release
782
 
        the table locks on the system tables.  This means that if
783
 
        MySQL crashes while creating a new primary key inside
784
 
        row_merge_build_indexes(), indexed_table will not be dropped
785
 
        by trx_rollback_active().  It will have to be recovered or
786
 
        dropped by the database administrator. */
 
753
        the table locks on the system tables.  Unfortunately, this
 
754
        means that if MySQL crashes while creating a new primary key
 
755
        inside row_merge_build_indexes(), indexed_table will not be
 
756
        dropped on crash recovery.  Thus, it will become orphaned. */
787
757
        trx_commit_for_mysql(trx);
788
758
 
789
759
        row_mysql_unlock_data_dictionary(trx);
813
783
                                        index, num_of_idx, i_table);
814
784
 
815
785
error_handling:
 
786
#ifdef UNIV_DEBUG
 
787
        /* TODO: At the moment we can't handle the following statement
 
788
        in our debugging code below:
 
789
 
 
790
        alter table t drop index b, add index (b);
 
791
 
 
792
        The fix will have to parse the SQL and note that the index
 
793
        being added has the same name as the the one being dropped and
 
794
        ignore that in the dup index check.*/
 
795
        //dict_table_check_for_dup_indexes(prebuilt->table);
 
796
#endif
816
797
 
817
798
        /* After an error, remove all those index definitions from the
818
799
        dictionary which were defined. */
825
806
                row_mysql_lock_data_dictionary(trx);
826
807
                dict_locked = TRUE;
827
808
 
828
 
                ut_d(dict_table_check_for_dup_indexes(prebuilt->table, TRUE));
829
 
 
830
809
                if (!new_primary) {
831
810
                        error = row_merge_rename_indexes(trx, indexed_table);
832
811
 
873
852
                indexed_table->n_mysql_handles_opened++;
874
853
 
875
854
                error = row_merge_drop_table(trx, innodb_table);
876
 
                innodb_table = indexed_table;
877
855
                goto convert_error;
878
856
 
879
857
        case DB_TOO_BIG_RECORD:
887
865
                prebuilt->trx->error_info = NULL;
888
866
                /* fall through */
889
867
        default:
890
 
                trx->error_state = DB_SUCCESS;
891
 
 
892
868
                if (new_primary) {
893
 
                        if (indexed_table != innodb_table) {
894
 
                                row_merge_drop_table(trx, indexed_table);
895
 
                        }
 
869
                        row_merge_drop_table(trx, indexed_table);
896
870
                } else {
897
871
                        if (!dict_locked) {
898
872
                                row_mysql_lock_data_dictionary(trx);
916
890
        }
917
891
 
918
892
        if (dict_locked) {
919
 
                ut_d(dict_table_check_for_dup_indexes(innodb_table, FALSE));
920
893
                row_mysql_unlock_data_dictionary(trx);
921
894
        }
922
895
 
935
908
int
936
909
ha_innobase::prepare_drop_index(
937
910
/*============================*/
938
 
                                Session *session,
939
911
        Table*  i_table,        /*!< in: Table where indexes are dropped */
940
912
        uint*   key_num,        /*!< in: Key nums to be dropped */
941
913
        uint    num_of_keys)    /*!< in: Number of keys to be dropped */
951
923
                return(HA_ERR_WRONG_COMMAND);
952
924
        }
953
925
 
954
 
        update_session(session);
 
926
        update_session();
955
927
 
956
928
        trx_search_latch_release_if_reserved(prebuilt->trx);
957
929
        trx = prebuilt->trx;
959
931
        /* Test and mark all the indexes to be dropped */
960
932
 
961
933
        row_mysql_lock_data_dictionary(trx);
962
 
        ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
963
934
 
964
935
        /* Check that none of the indexes have previously been flagged
965
936
        for deletion. */
973
944
        }
974
945
 
975
946
        for (n_key = 0; n_key < num_of_keys; n_key++) {
976
 
                const KeyInfo*  key;
 
947
                const KEY*      key;
977
948
                dict_index_t*   index;
978
949
 
979
950
                key = i_table->key_info + key_num[n_key];
1005
976
                index->to_be_dropped = TRUE;
1006
977
        }
1007
978
 
1008
 
        /* If FOREIGN_KEY_CHECKS = 1 you may not drop an index defined
 
979
        /* If FOREIGN_KEY_CHECK = 1 you may not drop an index defined
1009
980
        for a foreign key constraint because InnoDB requires that both
1010
 
        tables contain indexes for the constraint. Such index can
1011
 
        be dropped only if FOREIGN_KEY_CHECKS is set to 0.
1012
 
        Note that CREATE INDEX id ON table does a CREATE INDEX and
1013
 
        DROP INDEX, and we can ignore here foreign keys because a
1014
 
        new index for the foreign key has already been created.
 
981
        tables contain indexes for the constraint.  Note that CREATE
 
982
        INDEX id ON table does a CREATE INDEX and DROP INDEX, and we
 
983
        can ignore here foreign keys because a new index for the
 
984
        foreign key has already been created.
1015
985
 
1016
986
        We check for the foreign key constraints after marking the
1017
987
        candidate indexes for deletion, because when we check for an
1126
1096
                } while (index);
1127
1097
        }
1128
1098
 
1129
 
        ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
1130
1099
        row_mysql_unlock_data_dictionary(trx);
1131
1100
 
1132
1101
        return(err);
1139
1108
int
1140
1109
ha_innobase::final_drop_index(
1141
1110
/*==========================*/
1142
 
                              Session *session,
1143
1111
        Table*  )               /*!< in: Table where indexes are dropped */
1144
1112
{
1145
1113
        dict_index_t*   index;          /*!< Index to be dropped */
1150
1118
                return(HA_ERR_WRONG_COMMAND);
1151
1119
        }
1152
1120
 
1153
 
        update_session(session);
 
1121
        update_session();
1154
1122
 
1155
1123
        trx_search_latch_release_if_reserved(prebuilt->trx);
1156
1124
        trx_start_if_not_started(prebuilt->trx);
1171
1139
                prebuilt->table->flags, user_session);
1172
1140
 
1173
1141
        row_mysql_lock_data_dictionary(trx);
1174
 
        ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
1175
1142
 
1176
1143
        if (UNIV_UNLIKELY(err)) {
1177
1144
 
1208
1175
                ut_a(!index->to_be_dropped);
1209
1176
        }
1210
1177
 
1211
 
        /* We will need to rebuild index translation table. Set
1212
 
        valid index entry count in the translation table to zero */
1213
 
        share->idx_trans_tbl.index_count = 0;
 
1178
#ifdef UNIV_DEBUG
 
1179
        dict_table_check_for_dup_indexes(prebuilt->table);
 
1180
#endif
1214
1181
 
1215
1182
func_exit:
1216
 
        ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
1217
1183
        trx_commit_for_mysql(trx);
1218
1184
        trx_commit_for_mysql(prebuilt->trx);
1219
1185
        row_mysql_unlock_data_dictionary(trx);
1233
1199
 
1234
1200
        return(err);
1235
1201
}
1236
 
#endif