~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/innobase/drizzle/handler0alter.cc

  • Committer: Brian Aker
  • Date: 2009-02-10 00:14:40 UTC
  • Revision ID: brian@tangent.org-20090210001440-qjg8eofh3h93064b
Adding Multi-threaded Scheduler into the system.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*****************************************************************************
2
 
 
3
 
Copyright (C) 2005, 2010, Innobase Oy. All Rights Reserved.
4
 
 
5
 
This program is free software; you can redistribute it and/or modify it under
6
 
the terms of the GNU General Public License as published by the Free Software
7
 
Foundation; version 2 of the License.
8
 
 
9
 
This program is distributed in the hope that it will be useful, but WITHOUT
10
 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
 
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
 
 
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
16
 
 
17
 
*****************************************************************************/
18
 
 
19
 
/**************************************************//**
20
 
@file handler/handler0alter.cc
 
1
/******************************************************
21
2
Smart ALTER TABLE
 
3
 
 
4
(c) 2005-2008 Innobase Oy
22
5
*******************************************************/
23
6
 
24
 
#include <config.h>
 
7
#include <drizzled/server_includes.h>
25
8
#include <drizzled/error.h>
26
 
#include <drizzled/charset_info.h>
 
9
#include <mystrings/m_ctype.h>
27
10
#include <drizzled/field.h>
28
11
#include <drizzled/table.h>
29
12
#include <drizzled/field/varstring.h>
30
 
#include <drizzled/internal/my_sys.h>
31
13
 
 
14
extern "C" {
32
15
#include "log0log.h"
33
16
#include "row0merge.h"
34
17
#include "srv0srv.h"
36
19
#include "trx0roll.h"
37
20
#include "ha_prototypes.h"
38
21
#include "handler0alter.h"
 
22
}
39
23
 
40
24
#include "ha_innodb.h"
41
25
#include "handler0vars.h"
42
26
 
43
 
/*************************************************************//**
 
27
/*****************************************************************
44
28
Copies an InnoDB column to a MySQL field.  This function is
45
29
adapted from row_sel_field_store_in_mysql_format(). */
46
30
static
47
31
void
48
32
innobase_col_to_mysql(
49
33
/*==================*/
50
 
        const dict_col_t*       col,    /*!< in: InnoDB column */
51
 
        const unsigned char*    data,   /*!< in: InnoDB column data */
52
 
        ulint                   len,    /*!< in: length of data, in bytes */
53
 
        Field*                  field)  /*!< in/out: MySQL field */
 
34
        const dict_col_t*       col,    /* in: InnoDB column */
 
35
        const unsigned char*            data,   /* in: InnoDB column data */
 
36
        ulint                   len,    /* in: length of data, in bytes */
 
37
        Field*                  field)  /* in/out: MySQL field */
54
38
{
55
39
        unsigned char*  ptr;
56
40
        unsigned char*  dest    = field->ptr;
101
85
#ifdef UNIV_DEBUG
102
86
        case DATA_MYSQL:
103
87
                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);
 
88
                ut_ad(col->mbmaxlen >= col->mbminlen);
 
89
                ut_ad(col->mbmaxlen > col->mbminlen || flen == len);
108
90
                memcpy(dest, data, len);
109
91
                break;
110
92
 
128
110
        }
129
111
}
130
112
 
131
 
/*************************************************************//**
132
 
Copies an InnoDB record to table->getInsertRecord(). */
133
 
UNIV_INTERN
 
113
/*****************************************************************
 
114
Copies an InnoDB record to table->record[0]. */
 
115
extern "C" UNIV_INTERN
134
116
void
135
117
innobase_rec_to_mysql(
136
118
/*==================*/
137
 
        Table*                  table,          /*!< in/out: MySQL table */
138
 
        const rec_t*            rec,            /*!< in: record */
139
 
        const dict_index_t*     index,          /*!< in: index */
140
 
        const ulint*            offsets)        /*!< in: rec_get_offsets(
 
119
        Table*                  table,          /* in/out: MySQL table */
 
120
        const rec_t*            rec,            /* in: record */
 
121
        const dict_index_t*     index,          /* in: index */
 
122
        const ulint*            offsets)        /* in: rec_get_offsets(
141
123
                                                rec, index, ...) */
142
124
{
143
 
        uint    n_fields        = table->getShare()->sizeFields();
 
125
        uint    n_fields        = table->s->fields;
144
126
        uint    i;
145
127
 
146
128
        ut_ad(n_fields == dict_table_get_n_user_cols(index->table));
147
129
 
148
130
        for (i = 0; i < n_fields; i++) {
149
 
                Field*          field   = table->getField(i);
 
131
                Field*          field   = table->field[i];
150
132
                ulint           ipos;
151
133
                ulint           ilen;
152
134
                const unsigned char*    ifield;
178
160
        }
179
161
}
180
162
 
181
 
/*************************************************************//**
182
 
Resets table->getInsertRecord(). */
183
 
UNIV_INTERN
 
163
/*****************************************************************
 
164
Resets table->record[0]. */
 
165
extern "C" UNIV_INTERN
184
166
void
185
167
innobase_rec_reset(
186
168
/*===============*/
187
 
        Table*                  table)          /*!< in/out: MySQL table */
 
169
        Table*                  table)          /* in/out: MySQL table */
188
170
{
189
 
        uint    n_fields        = table->getShare()->sizeFields();
 
171
        uint    n_fields        = table->s->fields;
190
172
        uint    i;
191
173
 
192
174
        for (i = 0; i < n_fields; i++) {
193
 
                table->getField(i)->set_default();
 
175
                table->field[i]->set_default();
194
176
        }
195
177
}
196
178
 
197
 
#if 0 // This is a part of the fast index code.
198
 
/******************************************************************//**
 
179
/**********************************************************************
199
180
Removes the filename encoding of a database and table name. */
200
181
static
201
182
void
202
183
innobase_convert_tablename(
203
184
/*=======================*/
204
 
        char*   s)      /*!< in: identifier; out: decoded identifier */
 
185
        char*   s)      /* in: identifier; out: decoded identifier */
205
186
{
 
187
        uint    errors;
206
188
 
207
189
        char*   slash = strchr(s, '/');
208
190
 
210
192
                char*   t;
211
193
                /* Temporarily replace the '/' with NUL. */
212
194
                *slash = 0;
213
 
                strncpy(s, s, slash - s + 1);
 
195
                /* Convert the database name. */
 
196
                strconvert(&my_charset_filename, s, system_charset_info,
 
197
                           s, slash - s + 1, &errors);
214
198
 
215
199
                t = s + strlen(s);
216
200
                ut_ad(slash >= t);
218
202
                *t++ = '.';
219
203
                slash++;
220
204
                /* Convert the table name. */
221
 
                strncpy(t, slash, slash - t + strlen(slash));
 
205
                strconvert(&my_charset_filename, slash, system_charset_info,
 
206
                           t, slash - t + strlen(slash), &errors);
 
207
        } else {
 
208
                strconvert(&my_charset_filename, s,
 
209
                           system_charset_info, s, strlen(s), &errors);
222
210
        }
223
211
}
224
212
 
225
 
 
226
 
/*******************************************************************//**
227
 
This function checks that index keys are sensible.
228
 
@return 0 or error number */
 
213
/***********************************************************************
 
214
This function checks that index keys are sensible. */
229
215
static
230
216
int
231
217
innobase_check_index_keys(
232
218
/*======================*/
233
 
        const KeyInfo*  key_info,       /*!< in: Indexes to be created */
234
 
        ulint           num_of_keys,    /*!< in: Number of indexes to
 
219
                                        /* out: 0 or error number */
 
220
        const KEY*      key_info,       /* in: Indexes to be created */
 
221
        ulint           num_of_keys)    /* in: Number of indexes to
235
222
                                        be created */
236
 
        const dict_table_t*     table)  /*!< in: Existing indexes */
237
223
{
238
224
        ulint           key_num;
239
225
 
241
227
        ut_ad(num_of_keys);
242
228
 
243
229
        for (key_num = 0; key_num < num_of_keys; key_num++) {
244
 
                const KeyInfo&  key = key_info[key_num];
 
230
                const KEY&      key = key_info[key_num];
245
231
 
246
232
                /* Check that the same index name does not appear
247
233
                twice in indexes to be created. */
248
234
 
249
235
                for (ulint i = 0; i < key_num; i++) {
250
 
                        const KeyInfo&  key2 = key_info[i];
 
236
                        const KEY&      key2 = key_info[i];
251
237
 
252
238
                        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);
 
239
                                errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: key name `%s` appears"
 
240
                                                " twice in CREATE INDEX\n",
 
241
                                                key.name);
269
242
 
270
243
                                return(ER_WRONG_NAME_FOR_INDEX);
271
244
                        }
273
246
 
274
247
                /* Check that MySQL does not try to create a column
275
248
                prefix index field on an inappropriate data type and
276
 
                that the same column does not appear twice in the index. */
 
249
                that the same colum does not appear twice in the index. */
277
250
 
278
251
                for (ulint i = 0; i < key.key_parts; i++) {
279
 
                        const KeyPartInfo&      key_part1
 
252
                        const KEY_PART_INFO&    key_part1
280
253
                                = key.key_part[i];
281
254
                        const Field*            field
282
255
                                = key_part1.field;
304
277
                                        }
305
278
                                }
306
279
 
307
 
                                my_error(ER_WRONG_KEY_COLUMN, MYF(0),
308
 
                                         field->field_name);
 
280
                                errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: MySQL is trying to"
 
281
                                                " create a column prefix"
 
282
                                                " index field on an"
 
283
                                                " inappropriate data type."
 
284
                                                " column `%s`,"
 
285
                                                " index `%s`.\n",
 
286
                                                field->field_name,
 
287
                                                key.name);
309
288
                                return(ER_WRONG_KEY_COLUMN);
310
289
                        }
311
290
 
312
291
                        for (ulint j = 0; j < i; j++) {
313
 
                                const KeyPartInfo&      key_part2
 
292
                                const KEY_PART_INFO&    key_part2
314
293
                                        = key.key_part[j];
315
294
 
316
295
                                if (strcmp(key_part1.field->field_name,
318
297
                                        continue;
319
298
                                }
320
299
 
321
 
                                my_error(ER_WRONG_KEY_COLUMN, MYF(0),
322
 
                                         key_part1.field->field_name);
 
300
                                errmsg_printf(ERRMSG_LVL_ERROR, "InnoDB: column `%s`"
 
301
                                                " is not allowed to occur"
 
302
                                                " twice in index `%s`.\n",
 
303
                                                key_part1.field->field_name,
 
304
                                                key.name);
323
305
                                return(ER_WRONG_KEY_COLUMN);
324
306
                        }
325
307
                }
328
310
        return(0);
329
311
}
330
312
 
331
 
/*******************************************************************//**
 
313
/***********************************************************************
332
314
Create index field definition for key part */
333
315
static
334
316
void
335
317
innobase_create_index_field_def(
336
318
/*============================*/
337
 
        KeyPartInfo*            key_part,       /*!< in: MySQL key definition */
338
 
        mem_heap_t*             heap,           /*!< in: memory heap */
339
 
        merge_index_field_t*    index_field)    /*!< out: index field
 
319
        KEY_PART_INFO*          key_part,       /* in: MySQL key definition */
 
320
        mem_heap_t*             heap,           /* in: memory heap */
 
321
        merge_index_field_t*    index_field)    /* out: index field
340
322
                                                definition for key_part */
341
323
{
342
324
        Field*          field;
368
350
        return;
369
351
}
370
352
 
371
 
/*******************************************************************//**
 
353
/***********************************************************************
372
354
Create index definition for key */
373
355
static
374
356
void
375
357
innobase_create_index_def(
376
358
/*======================*/
377
 
        KeyInfo*                        key,            /*!< in: key definition */
378
 
        bool                    new_primary,    /*!< in: TRUE=generating
 
359
        KEY*                    key,            /* in: key definition */
 
360
        bool                    new_primary,    /* in: TRUE=generating
379
361
                                                a new primary key
380
362
                                                on the table */
381
 
        bool                    key_primary,    /*!< in: TRUE if this key
 
363
        bool                    key_primary,    /* in: TRUE if this key
382
364
                                                is a primary key */
383
 
        merge_index_def_t*      index,          /*!< out: index definition */
384
 
        mem_heap_t*             heap)           /*!< in: heap where memory
 
365
        merge_index_def_t*      index,          /* out: index definition */
 
366
        mem_heap_t*             heap)           /* in: heap where memory
385
367
                                                is allocated */
386
368
{
387
369
        ulint   i;
420
402
        return;
421
403
}
422
404
 
423
 
/*******************************************************************//**
 
405
/***********************************************************************
424
406
Copy index field definition */
425
407
static
426
408
void
427
409
innobase_copy_index_field_def(
428
410
/*==========================*/
429
 
        const dict_field_t*     field,          /*!< in: definition to copy */
430
 
        merge_index_field_t*    index_field)    /*!< out: copied definition */
 
411
        const dict_field_t*     field,          /* in: definition to copy */
 
412
        merge_index_field_t*    index_field)    /* out: copied definition */
431
413
{
432
414
        assert(field != NULL);
433
415
        assert(index_field != NULL);
438
420
        return;
439
421
}
440
422
 
441
 
/*******************************************************************//**
 
423
/***********************************************************************
442
424
Copy index definition for the index */
443
425
static
444
426
void
445
427
innobase_copy_index_def(
446
428
/*====================*/
447
 
        const dict_index_t*     index,  /*!< in: index definition to copy */
448
 
        merge_index_def_t*      new_index,/*!< out: Index definition */
449
 
        mem_heap_t*             heap)   /*!< in: heap where allocated */
 
429
        const dict_index_t*     index,  /* in: index definition to copy */
 
430
        merge_index_def_t*      new_index,/* out: Index definition */
 
431
        mem_heap_t*             heap)   /* in: heap where allocated */
450
432
{
451
433
        ulint   n_fields;
452
434
        ulint   i;
474
456
        return;
475
457
}
476
458
 
477
 
/*******************************************************************//**
 
459
/***********************************************************************
478
460
Create an index table where indexes are ordered as follows:
479
461
 
480
462
IF a new primary key is defined for the table THEN
489
471
 
490
472
ENDIF
491
473
 
492
 
 
493
 
@return key definitions or NULL */
494
 
 
 
474
*/
495
475
static
496
476
merge_index_def_t*
497
477
innobase_create_key_def(
498
478
/*====================*/
499
 
        trx_t*          trx,            /*!< in: trx */
500
 
        const dict_table_t*table,               /*!< in: table definition */
501
 
        mem_heap_t*     heap,           /*!< in: heap where space for key
 
479
                                        /* out: key definitions or NULL */
 
480
        trx_t*          trx,            /* in: trx */
 
481
        const dict_table_t*table,               /* in: table definition */
 
482
        mem_heap_t*     heap,           /* in: heap where space for key
502
483
                                        definitions are allocated */
503
 
        KeyInfo*                key_info,       /*!< in: Indexes to be created */
504
 
        ulint&          n_keys)         /*!< in/out: Number of indexes to
 
484
        KEY*            key_info,       /* in: Indexes to be created */
 
485
        ulint&          n_keys)         /* in/out: Number of indexes to
505
486
                                        be created */
506
487
{
507
488
        ulint                   i = 0;
520
501
                                     key_info->name, "PRIMARY");
521
502
 
522
503
        /* 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. */
 
504
        columns, MySQL will treat it as a PRIMARY KEY unless the
 
505
        table already has one. */
526
506
 
527
507
        if (!new_primary && (key_info->flags & HA_NOSAME)
528
 
            && (!(key_info->flags & HA_KEY_HAS_PART_KEY_SEG))
529
508
            && row_table_got_default_clust_index(table)) {
530
 
                uint    key_part = key_info->key_parts;
 
509
                uint    key_part = key_info->key_parts;
531
510
 
532
511
                new_primary = TRUE;
533
512
 
534
513
                while (key_part--) {
535
 
                        if (key_info->key_part[key_part].null_bit == 0) {
 
514
                        if (key_info->key_part[key_part].key_type
 
515
                            & FIELDFLAG_MAYBE_NULL) {
536
516
                                new_primary = FALSE;
537
517
                                break;
538
518
                        }
581
561
        return(indexdefs);
582
562
}
583
563
 
584
 
/*******************************************************************//**
585
 
Create a temporary tablename using query id, thread id, and id
586
 
@return temporary tablename */
 
564
/***********************************************************************
 
565
Create a temporary tablename using query id, thread id, and id */
587
566
static
588
567
char*
589
568
innobase_create_temporary_tablename(
590
569
/*================================*/
591
 
        mem_heap_t*     heap,           /*!< in: memory heap */
592
 
        char            id,             /*!< in: identifier [0-9a-zA-Z] */
593
 
        const char*     table_name)     /*!< in: table name */
 
570
                                        /* out: temporary tablename */
 
571
        mem_heap_t*     heap,           /* in: memory heap */
 
572
        char            id,             /* in: identifier [0-9a-zA-Z] */
 
573
        const char*     table_name)     /* in: table name */
594
574
{
595
575
        char*                   name;
596
576
        ulint                   len;
606
586
        return(name);
607
587
}
608
588
 
609
 
 
610
 
/*******************************************************************//**
611
 
Create indexes.
612
 
@return 0 or error number */
 
589
/***********************************************************************
 
590
Create indexes. */
613
591
UNIV_INTERN
614
592
int
615
593
ha_innobase::add_index(
616
594
/*===================*/
617
 
                       Session *session,
618
 
        Table*  i_table,        /*!< in: Table where indexes are created */
619
 
        KeyInfo*        key_info,       /*!< in: Indexes to be created */
620
 
        uint    num_of_keys)    /*!< in: Number of indexes to be created */
 
595
                                /* out: 0 or error number */
 
596
        Table*  i_table,        /* in: Table where indexes are created */
 
597
        KEY*    key_info,       /* in: Indexes to be created */
 
598
        uint    num_of_keys)    /* in: Number of indexes to be created */
621
599
{
622
 
        dict_index_t**  index;          /*!< Index to be created */
623
 
        dict_table_t*   innodb_table;   /*!< InnoDB table in dictionary */
624
 
        dict_table_t*   indexed_table;  /*!< Table where indexes are created */
625
 
        merge_index_def_t* index_defs;  /*!< Index definitions */
626
 
        mem_heap_t*     heap;           /*!< Heap for index definitions */
627
 
        trx_t*          trx;            /*!< Transaction */
 
600
        dict_index_t**  index;          /* Index to be created */
 
601
        dict_table_t*   innodb_table;   /* InnoDB table in dictionary */
 
602
        dict_table_t*   indexed_table;  /* Table where indexes are created */
 
603
        merge_index_def_t* index_defs;  /* Index definitions */
 
604
        mem_heap_t*     heap;           /* Heap for index definitions */
 
605
        trx_t*          trx;            /* Transaction */
628
606
        ulint           num_of_idx;
629
607
        ulint           num_created     = 0;
630
608
        ibool           dict_locked     = FALSE;
631
609
        ulint           new_primary;
632
 
        int             error;
 
610
        ulint           error;
633
611
 
634
612
        ut_a(i_table);
635
613
        ut_a(key_info);
639
617
                return(HA_ERR_WRONG_COMMAND);
640
618
        }
641
619
 
642
 
        update_session(session);
 
620
        update_session();
643
621
 
644
622
        heap = mem_heap_create(1024);
645
623
 
646
624
        /* In case MySQL calls this in the middle of a SELECT query, release
647
625
        possible adaptive hash latch to avoid deadlocks of threads. */
648
626
        trx_search_latch_release_if_reserved(prebuilt->trx);
649
 
        trx_start_if_not_started(prebuilt->trx);
650
627
 
651
628
        /* Create a background transaction for the operations on
652
629
        the data dictionary tables. */
653
 
        trx = innobase_trx_allocate(user_session);
 
630
        trx = trx_allocate_for_mysql();
654
631
        trx_start_if_not_started(trx);
655
632
 
 
633
        trx->mysql_thd = user_session;
 
634
        trx->mysql_query_str = session_query(user_session);
 
635
 
656
636
        innodb_table = indexed_table
657
637
                = dict_table_get(prebuilt->table->name, FALSE);
658
638
 
659
 
        if (UNIV_UNLIKELY(!innodb_table)) {
660
 
                error = HA_ERR_NO_SUCH_TABLE;
661
 
                goto err_exit;
662
 
        }
 
639
        /* Check that index keys are sensible */
663
640
 
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
 
        }
 
641
        error = innobase_check_index_keys(key_info, num_of_keys);
672
642
 
673
643
        if (UNIV_UNLIKELY(error)) {
674
644
err_exit:
675
645
                mem_heap_free(heap);
676
 
                trx_general_rollback_for_mysql(trx, NULL);
 
646
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
677
647
                trx_free_for_mysql(trx);
678
648
                trx_commit_for_mysql(prebuilt->trx);
679
649
                return(error);
714
684
        row_mysql_lock_data_dictionary(trx);
715
685
        dict_locked = TRUE;
716
686
 
717
 
        ut_d(dict_table_check_for_dup_indexes(innodb_table, FALSE));
718
 
 
719
687
        /* If a new primary key is defined for the table we need
720
688
        to drop the original table and rebuild all indexes. */
721
689
 
748
716
                                        user_session);
749
717
                        }
750
718
 
751
 
                        ut_d(dict_table_check_for_dup_indexes(innodb_table,
752
 
                                                              FALSE));
753
719
                        row_mysql_unlock_data_dictionary(trx);
754
720
                        goto err_exit;
755
721
                }
774
740
 
775
741
        ut_ad(error == DB_SUCCESS);
776
742
 
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
743
        /* 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. */
 
744
        the table locks on the system tables.  Unfortunately, this
 
745
        means that if MySQL crashes while creating a new primary key
 
746
        inside row_merge_build_indexes(), indexed_table will not be
 
747
        dropped on crash recovery.  Thus, it will become orphaned. */
787
748
        trx_commit_for_mysql(trx);
788
749
 
789
750
        row_mysql_unlock_data_dictionary(trx);
813
774
                                        index, num_of_idx, i_table);
814
775
 
815
776
error_handling:
 
777
#ifdef UNIV_DEBUG
 
778
        /* TODO: At the moment we can't handle the following statement
 
779
        in our debugging code below:
 
780
 
 
781
        alter table t drop index b, add index (b);
 
782
 
 
783
        The fix will have to parse the SQL and note that the index
 
784
        being added has the same name as the the one being dropped and
 
785
        ignore that in the dup index check.*/
 
786
        //dict_table_check_for_dup_indexes(prebuilt->table);
 
787
#endif
816
788
 
817
789
        /* After an error, remove all those index definitions from the
818
790
        dictionary which were defined. */
825
797
                row_mysql_lock_data_dictionary(trx);
826
798
                dict_locked = TRUE;
827
799
 
828
 
                ut_d(dict_table_check_for_dup_indexes(prebuilt->table, TRUE));
829
 
 
830
800
                if (!new_primary) {
831
801
                        error = row_merge_rename_indexes(trx, indexed_table);
832
802
 
873
843
                indexed_table->n_mysql_handles_opened++;
874
844
 
875
845
                error = row_merge_drop_table(trx, innodb_table);
876
 
                innodb_table = indexed_table;
877
846
                goto convert_error;
878
847
 
879
848
        case DB_TOO_BIG_RECORD:
887
856
                prebuilt->trx->error_info = NULL;
888
857
                /* fall through */
889
858
        default:
890
 
                trx->error_state = DB_SUCCESS;
891
 
 
892
859
                if (new_primary) {
893
 
                        if (indexed_table != innodb_table) {
894
 
                                row_merge_drop_table(trx, indexed_table);
895
 
                        }
 
860
                        row_merge_drop_table(trx, indexed_table);
896
861
                } else {
897
862
                        if (!dict_locked) {
898
863
                                row_mysql_lock_data_dictionary(trx);
916
881
        }
917
882
 
918
883
        if (dict_locked) {
919
 
                ut_d(dict_table_check_for_dup_indexes(innodb_table, FALSE));
920
884
                row_mysql_unlock_data_dictionary(trx);
921
885
        }
922
886
 
928
892
        return(error);
929
893
}
930
894
 
931
 
/*******************************************************************//**
932
 
Prepare to drop some indexes of a table.
933
 
@return 0 or error number */
 
895
/***********************************************************************
 
896
Prepare to drop some indexes of a table. */
934
897
UNIV_INTERN
935
898
int
936
899
ha_innobase::prepare_drop_index(
937
900
/*============================*/
938
 
                                Session *session,
939
 
        Table*  i_table,        /*!< in: Table where indexes are dropped */
940
 
        uint*   key_num,        /*!< in: Key nums to be dropped */
941
 
        uint    num_of_keys)    /*!< in: Number of keys to be dropped */
 
901
                                /* out: 0 or error number */
 
902
        Table*  i_table,        /* in: Table where indexes are dropped */
 
903
        uint*   key_num,        /* in: Key nums to be dropped */
 
904
        uint    num_of_keys)    /* in: Number of keys to be dropped */
942
905
{
943
906
        trx_t*          trx;
944
907
        int             err = 0;
951
914
                return(HA_ERR_WRONG_COMMAND);
952
915
        }
953
916
 
954
 
        update_session(session);
 
917
        update_session();
955
918
 
956
919
        trx_search_latch_release_if_reserved(prebuilt->trx);
957
920
        trx = prebuilt->trx;
959
922
        /* Test and mark all the indexes to be dropped */
960
923
 
961
924
        row_mysql_lock_data_dictionary(trx);
962
 
        ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
963
925
 
964
926
        /* Check that none of the indexes have previously been flagged
965
927
        for deletion. */
973
935
        }
974
936
 
975
937
        for (n_key = 0; n_key < num_of_keys; n_key++) {
976
 
                const KeyInfo*  key;
 
938
                const KEY*      key;
977
939
                dict_index_t*   index;
978
940
 
979
941
                key = i_table->key_info + key_num[n_key];
993
955
 
994
956
                /* Refuse to drop the clustered index.  It would be
995
957
                better to automatically generate a clustered index,
996
 
                but drizzled::alter_table() will call this method only
 
958
                but mysql_alter_table() will call this method only
997
959
                after ha_innobase::add_index(). */
998
960
 
999
961
                if (dict_index_is_clust(index)) {
1005
967
                index->to_be_dropped = TRUE;
1006
968
        }
1007
969
 
1008
 
        /* If FOREIGN_KEY_CHECKS = 1 you may not drop an index defined
 
970
        /* If FOREIGN_KEY_CHECK = 1 you may not drop an index defined
1009
971
        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.
 
972
        tables contain indexes for the constraint.  Note that CREATE
 
973
        INDEX id ON table does a CREATE INDEX and DROP INDEX, and we
 
974
        can ignore here foreign keys because a new index for the
 
975
        foreign key has already been created.
1015
976
 
1016
977
        We check for the foreign key constraints after marking the
1017
978
        candidate indexes for deletion, because when we check for an
1126
1087
                } while (index);
1127
1088
        }
1128
1089
 
1129
 
        ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
1130
1090
        row_mysql_unlock_data_dictionary(trx);
1131
1091
 
1132
1092
        return(err);
1133
1093
}
1134
1094
 
1135
 
/*******************************************************************//**
1136
 
Drop the indexes that were passed to a successful prepare_drop_index().
1137
 
@return 0 or error number */
 
1095
/***********************************************************************
 
1096
Drop the indexes that were passed to a successful prepare_drop_index(). */
1138
1097
UNIV_INTERN
1139
1098
int
1140
1099
ha_innobase::final_drop_index(
1141
1100
/*==========================*/
1142
 
                              Session *session,
1143
 
        Table*  )               /*!< in: Table where indexes are dropped */
 
1101
                                /* out: 0 or error number */
 
1102
        Table*          )       /* in: Table where indexes are dropped */
1144
1103
{
1145
 
        dict_index_t*   index;          /*!< Index to be dropped */
1146
 
        trx_t*          trx;            /*!< Transaction */
 
1104
        dict_index_t*   index;          /* Index to be dropped */
 
1105
        trx_t*          trx;            /* Transaction */
1147
1106
        int             err;
1148
1107
 
1149
1108
        if (srv_created_new_raw || srv_force_recovery) {
1150
1109
                return(HA_ERR_WRONG_COMMAND);
1151
1110
        }
1152
1111
 
1153
 
        update_session(session);
 
1112
        update_session();
1154
1113
 
1155
1114
        trx_search_latch_release_if_reserved(prebuilt->trx);
1156
 
        trx_start_if_not_started(prebuilt->trx);
1157
1115
 
1158
1116
        /* Create a background transaction for the operations on
1159
1117
        the data dictionary tables. */
1160
 
        trx = innobase_trx_allocate(user_session);
 
1118
        trx = trx_allocate_for_mysql();
1161
1119
        trx_start_if_not_started(trx);
1162
1120
 
 
1121
        trx->mysql_thd = user_session;
 
1122
        trx->mysql_query_str = session_query(user_session);
 
1123
 
1163
1124
        /* Flag this transaction as a dictionary operation, so that
1164
1125
        the data dictionary will be locked in crash recovery. */
1165
1126
        trx_set_dict_operation(trx, TRX_DICT_OP_INDEX);
1171
1132
                prebuilt->table->flags, user_session);
1172
1133
 
1173
1134
        row_mysql_lock_data_dictionary(trx);
1174
 
        ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
1175
1135
 
1176
1136
        if (UNIV_UNLIKELY(err)) {
1177
1137
 
1208
1168
                ut_a(!index->to_be_dropped);
1209
1169
        }
1210
1170
 
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;
 
1171
#ifdef UNIV_DEBUG
 
1172
        dict_table_check_for_dup_indexes(prebuilt->table);
 
1173
#endif
1214
1174
 
1215
1175
func_exit:
1216
 
        ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
1217
1176
        trx_commit_for_mysql(trx);
1218
1177
        trx_commit_for_mysql(prebuilt->trx);
1219
1178
        row_mysql_unlock_data_dictionary(trx);
1233
1192
 
1234
1193
        return(err);
1235
1194
}
1236
 
#endif