~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

Rename of handler to Cursor.  You would not believe how long I have wanted
to do that.

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
 
 
31
extern "C" {
32
32
#include "log0log.h"
33
33
#include "row0merge.h"
34
34
#include "srv0srv.h"
36
36
#include "trx0roll.h"
37
37
#include "ha_prototypes.h"
38
38
#include "handler0alter.h"
 
39
}
39
40
 
40
41
#include "ha_innodb.h"
41
42
#include "handler0vars.h"
101
102
#ifdef UNIV_DEBUG
102
103
        case DATA_MYSQL:
103
104
                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);
 
105
                ut_ad(col->mbmaxlen >= col->mbminlen);
 
106
                ut_ad(col->mbmaxlen > col->mbminlen || flen == len);
108
107
                memcpy(dest, data, len);
109
108
                break;
110
109
 
129
128
}
130
129
 
131
130
/*************************************************************//**
132
 
Copies an InnoDB record to table->getInsertRecord(). */
133
 
UNIV_INTERN
 
131
Copies an InnoDB record to table->record[0]. */
 
132
extern "C" UNIV_INTERN
134
133
void
135
134
innobase_rec_to_mysql(
136
135
/*==================*/
140
139
        const ulint*            offsets)        /*!< in: rec_get_offsets(
141
140
                                                rec, index, ...) */
142
141
{
143
 
        uint    n_fields        = table->getShare()->sizeFields();
 
142
        uint    n_fields        = table->s->fields;
144
143
        uint    i;
145
144
 
146
145
        ut_ad(n_fields == dict_table_get_n_user_cols(index->table));
147
146
 
148
147
        for (i = 0; i < n_fields; i++) {
149
 
                Field*          field   = table->getField(i);
 
148
                Field*          field   = table->field[i];
150
149
                ulint           ipos;
151
150
                ulint           ilen;
152
151
                const unsigned char*    ifield;
179
178
}
180
179
 
181
180
/*************************************************************//**
182
 
Resets table->getInsertRecord(). */
183
 
UNIV_INTERN
 
181
Resets table->record[0]. */
 
182
extern "C" UNIV_INTERN
184
183
void
185
184
innobase_rec_reset(
186
185
/*===============*/
187
186
        Table*                  table)          /*!< in/out: MySQL table */
188
187
{
189
 
        uint    n_fields        = table->getShare()->sizeFields();
 
188
        uint    n_fields        = table->s->fields;
190
189
        uint    i;
191
190
 
192
191
        for (i = 0; i < n_fields; i++) {
193
 
                table->getField(i)->set_default();
 
192
                table->field[i]->set_default();
194
193
        }
195
194
}
196
195
 
197
 
#if 0 // This is a part of the fast index code.
198
196
/******************************************************************//**
199
197
Removes the filename encoding of a database and table name. */
200
198
static
222
220
        }
223
221
}
224
222
 
225
 
 
226
223
/*******************************************************************//**
227
224
This function checks that index keys are sensible.
228
225
@return 0 or error number */
230
227
int
231
228
innobase_check_index_keys(
232
229
/*======================*/
233
 
        const KeyInfo*  key_info,       /*!< in: Indexes to be created */
234
 
        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
235
232
                                        be created */
236
 
        const dict_table_t*     table)  /*!< in: Existing indexes */
237
233
{
238
234
        ulint           key_num;
239
235
 
241
237
        ut_ad(num_of_keys);
242
238
 
243
239
        for (key_num = 0; key_num < num_of_keys; key_num++) {
244
 
                const KeyInfo&  key = key_info[key_num];
 
240
                const KEY&      key = key_info[key_num];
245
241
 
246
242
                /* Check that the same index name does not appear
247
243
                twice in indexes to be created. */
248
244
 
249
245
                for (ulint i = 0; i < key_num; i++) {
250
 
                        const KeyInfo&  key2 = key_info[i];
 
246
                        const KEY&      key2 = key_info[i];
251
247
 
252
248
                        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);
 
249
                                errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: key name `%s` appears"
 
250
                                                " twice in CREATE INDEX\n",
 
251
                                                key.name);
269
252
 
270
253
                                return(ER_WRONG_NAME_FOR_INDEX);
271
254
                        }
273
256
 
274
257
                /* Check that MySQL does not try to create a column
275
258
                prefix index field on an inappropriate data type and
276
 
                that the same column does not appear twice in the index. */
 
259
                that the same colum does not appear twice in the index. */
277
260
 
278
261
                for (ulint i = 0; i < key.key_parts; i++) {
279
 
                        const KeyPartInfo&      key_part1
 
262
                        const KEY_PART_INFO&    key_part1
280
263
                                = key.key_part[i];
281
264
                        const Field*            field
282
265
                                = key_part1.field;
304
287
                                        }
305
288
                                }
306
289
 
307
 
                                my_error(ER_WRONG_KEY_COLUMN, MYF(0),
308
 
                                         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);
309
298
                                return(ER_WRONG_KEY_COLUMN);
310
299
                        }
311
300
 
312
301
                        for (ulint j = 0; j < i; j++) {
313
 
                                const KeyPartInfo&      key_part2
 
302
                                const KEY_PART_INFO&    key_part2
314
303
                                        = key.key_part[j];
315
304
 
316
305
                                if (strcmp(key_part1.field->field_name,
318
307
                                        continue;
319
308
                                }
320
309
 
321
 
                                my_error(ER_WRONG_KEY_COLUMN, MYF(0),
322
 
                                         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);
323
315
                                return(ER_WRONG_KEY_COLUMN);
324
316
                        }
325
317
                }
334
326
void
335
327
innobase_create_index_field_def(
336
328
/*============================*/
337
 
        KeyPartInfo*            key_part,       /*!< in: MySQL key definition */
 
329
        KEY_PART_INFO*          key_part,       /*!< in: MySQL key definition */
338
330
        mem_heap_t*             heap,           /*!< in: memory heap */
339
331
        merge_index_field_t*    index_field)    /*!< out: index field
340
332
                                                definition for key_part */
374
366
void
375
367
innobase_create_index_def(
376
368
/*======================*/
377
 
        KeyInfo*                        key,            /*!< in: key definition */
 
369
        KEY*                    key,            /*!< in: key definition */
378
370
        bool                    new_primary,    /*!< in: TRUE=generating
379
371
                                                a new primary key
380
372
                                                on the table */
491
483
 
492
484
 
493
485
@return key definitions or NULL */
494
 
 
495
486
static
496
487
merge_index_def_t*
497
488
innobase_create_key_def(
500
491
        const dict_table_t*table,               /*!< in: table definition */
501
492
        mem_heap_t*     heap,           /*!< in: heap where space for key
502
493
                                        definitions are allocated */
503
 
        KeyInfo*                key_info,       /*!< in: Indexes to be created */
 
494
        KEY*            key_info,       /*!< in: Indexes to be created */
504
495
        ulint&          n_keys)         /*!< in/out: Number of indexes to
505
496
                                        be created */
506
497
{
520
511
                                     key_info->name, "PRIMARY");
521
512
 
522
513
        /* 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. */
 
514
        columns, MySQL will treat it as a PRIMARY KEY unless the
 
515
        table already has one. */
526
516
 
527
517
        if (!new_primary && (key_info->flags & HA_NOSAME)
528
 
            && (!(key_info->flags & HA_KEY_HAS_PART_KEY_SEG))
529
518
            && row_table_got_default_clust_index(table)) {
530
 
                uint    key_part = key_info->key_parts;
 
519
                uint    key_part = key_info->key_parts;
531
520
 
532
521
                new_primary = TRUE;
533
522
 
606
595
        return(name);
607
596
}
608
597
 
609
 
 
610
598
/*******************************************************************//**
611
599
Create indexes.
612
600
@return 0 or error number */
614
602
int
615
603
ha_innobase::add_index(
616
604
/*===================*/
617
 
                       Session *session,
618
605
        Table*  i_table,        /*!< in: Table where indexes are created */
619
 
        KeyInfo*        key_info,       /*!< in: Indexes to be created */
 
606
        KEY*    key_info,       /*!< in: Indexes to be created */
620
607
        uint    num_of_keys)    /*!< in: Number of indexes to be created */
621
608
{
622
609
        dict_index_t**  index;          /*!< Index to be created */
629
616
        ulint           num_created     = 0;
630
617
        ibool           dict_locked     = FALSE;
631
618
        ulint           new_primary;
632
 
        int             error;
 
619
        ulint           error;
633
620
 
634
621
        ut_a(i_table);
635
622
        ut_a(key_info);
639
626
                return(HA_ERR_WRONG_COMMAND);
640
627
        }
641
628
 
642
 
        update_session(session);
 
629
        update_session();
643
630
 
644
631
        heap = mem_heap_create(1024);
645
632
 
656
643
        innodb_table = indexed_table
657
644
                = dict_table_get(prebuilt->table->name, FALSE);
658
645
 
659
 
        if (UNIV_UNLIKELY(!innodb_table)) {
660
 
                error = HA_ERR_NO_SUCH_TABLE;
661
 
                goto err_exit;
662
 
        }
 
646
        /* Check that index keys are sensible */
663
647
 
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
 
        }
 
648
        error = innobase_check_index_keys(key_info, num_of_keys);
672
649
 
673
650
        if (UNIV_UNLIKELY(error)) {
674
651
err_exit:
675
652
                mem_heap_free(heap);
676
 
                trx_general_rollback_for_mysql(trx, NULL);
 
653
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
677
654
                trx_free_for_mysql(trx);
678
655
                trx_commit_for_mysql(prebuilt->trx);
679
656
                return(error);
714
691
        row_mysql_lock_data_dictionary(trx);
715
692
        dict_locked = TRUE;
716
693
 
717
 
        ut_d(dict_table_check_for_dup_indexes(innodb_table, FALSE));
718
 
 
719
694
        /* If a new primary key is defined for the table we need
720
695
        to drop the original table and rebuild all indexes. */
721
696
 
748
723
                                        user_session);
749
724
                        }
750
725
 
751
 
                        ut_d(dict_table_check_for_dup_indexes(innodb_table,
752
 
                                                              FALSE));
753
726
                        row_mysql_unlock_data_dictionary(trx);
754
727
                        goto err_exit;
755
728
                }
774
747
 
775
748
        ut_ad(error == DB_SUCCESS);
776
749
 
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
750
        /* 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. */
 
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. */
787
755
        trx_commit_for_mysql(trx);
788
756
 
789
757
        row_mysql_unlock_data_dictionary(trx);
813
781
                                        index, num_of_idx, i_table);
814
782
 
815
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
816
795
 
817
796
        /* After an error, remove all those index definitions from the
818
797
        dictionary which were defined. */
825
804
                row_mysql_lock_data_dictionary(trx);
826
805
                dict_locked = TRUE;
827
806
 
828
 
                ut_d(dict_table_check_for_dup_indexes(prebuilt->table, TRUE));
829
 
 
830
807
                if (!new_primary) {
831
808
                        error = row_merge_rename_indexes(trx, indexed_table);
832
809
 
873
850
                indexed_table->n_mysql_handles_opened++;
874
851
 
875
852
                error = row_merge_drop_table(trx, innodb_table);
876
 
                innodb_table = indexed_table;
877
853
                goto convert_error;
878
854
 
879
855
        case DB_TOO_BIG_RECORD:
887
863
                prebuilt->trx->error_info = NULL;
888
864
                /* fall through */
889
865
        default:
890
 
                trx->error_state = DB_SUCCESS;
891
 
 
892
866
                if (new_primary) {
893
 
                        if (indexed_table != innodb_table) {
894
 
                                row_merge_drop_table(trx, indexed_table);
895
 
                        }
 
867
                        row_merge_drop_table(trx, indexed_table);
896
868
                } else {
897
869
                        if (!dict_locked) {
898
870
                                row_mysql_lock_data_dictionary(trx);
916
888
        }
917
889
 
918
890
        if (dict_locked) {
919
 
                ut_d(dict_table_check_for_dup_indexes(innodb_table, FALSE));
920
891
                row_mysql_unlock_data_dictionary(trx);
921
892
        }
922
893
 
935
906
int
936
907
ha_innobase::prepare_drop_index(
937
908
/*============================*/
938
 
                                Session *session,
939
909
        Table*  i_table,        /*!< in: Table where indexes are dropped */
940
910
        uint*   key_num,        /*!< in: Key nums to be dropped */
941
911
        uint    num_of_keys)    /*!< in: Number of keys to be dropped */
951
921
                return(HA_ERR_WRONG_COMMAND);
952
922
        }
953
923
 
954
 
        update_session(session);
 
924
        update_session();
955
925
 
956
926
        trx_search_latch_release_if_reserved(prebuilt->trx);
957
927
        trx = prebuilt->trx;
959
929
        /* Test and mark all the indexes to be dropped */
960
930
 
961
931
        row_mysql_lock_data_dictionary(trx);
962
 
        ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
963
932
 
964
933
        /* Check that none of the indexes have previously been flagged
965
934
        for deletion. */
973
942
        }
974
943
 
975
944
        for (n_key = 0; n_key < num_of_keys; n_key++) {
976
 
                const KeyInfo*  key;
 
945
                const KEY*      key;
977
946
                dict_index_t*   index;
978
947
 
979
948
                key = i_table->key_info + key_num[n_key];
993
962
 
994
963
                /* Refuse to drop the clustered index.  It would be
995
964
                better to automatically generate a clustered index,
996
 
                but drizzled::alter_table() will call this method only
 
965
                but mysql_alter_table() will call this method only
997
966
                after ha_innobase::add_index(). */
998
967
 
999
968
                if (dict_index_is_clust(index)) {
1005
974
                index->to_be_dropped = TRUE;
1006
975
        }
1007
976
 
1008
 
        /* If FOREIGN_KEY_CHECKS = 1 you may not drop an index defined
 
977
        /* If FOREIGN_KEY_CHECK = 1 you may not drop an index defined
1009
978
        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.
 
979
        tables contain indexes for the constraint.  Note that CREATE
 
980
        INDEX id ON table does a CREATE INDEX and DROP INDEX, and we
 
981
        can ignore here foreign keys because a new index for the
 
982
        foreign key has already been created.
1015
983
 
1016
984
        We check for the foreign key constraints after marking the
1017
985
        candidate indexes for deletion, because when we check for an
1126
1094
                } while (index);
1127
1095
        }
1128
1096
 
1129
 
        ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
1130
1097
        row_mysql_unlock_data_dictionary(trx);
1131
1098
 
1132
1099
        return(err);
1139
1106
int
1140
1107
ha_innobase::final_drop_index(
1141
1108
/*==========================*/
1142
 
                              Session *session,
1143
1109
        Table*  )               /*!< in: Table where indexes are dropped */
1144
1110
{
1145
1111
        dict_index_t*   index;          /*!< Index to be dropped */
1150
1116
                return(HA_ERR_WRONG_COMMAND);
1151
1117
        }
1152
1118
 
1153
 
        update_session(session);
 
1119
        update_session();
1154
1120
 
1155
1121
        trx_search_latch_release_if_reserved(prebuilt->trx);
1156
1122
        trx_start_if_not_started(prebuilt->trx);
1171
1137
                prebuilt->table->flags, user_session);
1172
1138
 
1173
1139
        row_mysql_lock_data_dictionary(trx);
1174
 
        ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
1175
1140
 
1176
1141
        if (UNIV_UNLIKELY(err)) {
1177
1142
 
1208
1173
                ut_a(!index->to_be_dropped);
1209
1174
        }
1210
1175
 
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;
 
1176
#ifdef UNIV_DEBUG
 
1177
        dict_table_check_for_dup_indexes(prebuilt->table);
 
1178
#endif
1214
1179
 
1215
1180
func_exit:
1216
 
        ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
1217
1181
        trx_commit_for_mysql(trx);
1218
1182
        trx_commit_for_mysql(prebuilt->trx);
1219
1183
        row_mysql_unlock_data_dictionary(trx);
1233
1197
 
1234
1198
        return(err);
1235
1199
}
1236
 
#endif