1
# name : innodb_expand_fast_index_creation.patch
4
# Expands the applicability of InnoDB fast index creation to mysqldump,
5
# ALTER TABLE and OPTIMIZE TABLE.
7
--- a/client/client_priv.h 2011-03-31 12:04:39.000000000 +0400
8
+++ b/client/client_priv.h 2011-03-31 12:10:21.000000000 +0400
12
OPT_NO_REMOVE_EOL_CARRET,
13
+ OPT_INNODB_OPTIMIZE_KEYS,
16
--- a/client/mysqldump.c 2011-03-31 12:04:37.000000000 +0400
17
+++ b/client/mysqldump.c 2011-03-31 12:05:39.000000000 +0400
24
#include "client_priv.h"
28
static my_bool server_supports_sql_no_fcache= FALSE;
30
+static my_bool opt_innodb_optimize_keys= FALSE;
33
Dynamic_string wrapper functions. In this file use these
34
wrappers, they will terminate the process if there is
39
+LIST *skipped_keys_list;
41
static struct my_option my_long_options[] =
43
{"all", OPT_ALL, "Deprecated. Use --create-options instead.",
45
"be specified with both database and table names, e.g., "
46
"--ignore-table=database.table.",
47
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
48
+ {"innodb-optimize-keys", OPT_INNODB_OPTIMIZE_KEYS,
49
+ "Use InnoDB fast index creation by creating secondary indexes after "
50
+ "dumping the data.",
51
+ &opt_innodb_optimize_keys, &opt_innodb_optimize_keys, 0, GET_BOOL, NO_ARG,
53
{"insert-ignore", OPT_INSERT_IGNORE, "Insert rows with INSERT IGNORE.",
54
&opt_ignore, &opt_ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
56
@@ -2240,6 +2250,77 @@
60
+ Remove secondary/foreign key definitions from a given SHOW CREATE TABLE string
61
+ and store them into a temporary list to be used later.
64
+ skip_secondary_keys()
65
+ create_str SHOW CREATE TABLE output
70
+ Stores all lines starting with "KEY" or "UNIQUE KEY" or "CONSTRAINT"
71
+ into skipped_keys_list and removes them from the input string.
72
+ Ignoring FOREIGN KEYS constraints when creating the table is ok, because
73
+ mysqldump sets foreign_key_checks to 0 anyway.
76
+static void skip_secondary_keys(char *create_str)
79
+ char *last_comma = NULL;
81
+ strend= create_str + strlen(create_str);
86
+ char *tmp, *orig_ptr;
89
+ /* Skip leading whitespace */
90
+ while (*ptr && my_isspace(charset_info, *ptr))
93
+ /* Read the next line */
94
+ for (tmp= ptr; *tmp != '\n' && *tmp != '\0'; tmp++);
96
+ /* Is it a secondary index definition? */
98
+ (!strncmp(ptr, "UNIQUE KEY ", sizeof("UNIQUE KEY ") - 1) ||
99
+ !strncmp(ptr, "KEY ", sizeof("KEY ") - 1) ||
100
+ !strncmp(ptr, "CONSTRAINT ", sizeof("CONSTRAINT ") - 1)))
102
+ char *data, *end= tmp - 1;
104
+ /* Remove the trailing comma */
107
+ data= my_strndup(ptr, end - ptr + 1, MYF(MY_FAE));
108
+ skipped_keys_list= list_cons(data, skipped_keys_list);
110
+ memmove(orig_ptr, tmp + 1, strend - tmp);
112
+ strend-= tmp + 1 - ptr;
114
+ /* Remove the comma on the previos line */
115
+ if (last_comma != NULL)
123
+ if (tmp[-1] == ',')
124
+ last_comma= tmp - 1;
125
+ ptr= (*tmp == '\0') ? tmp : tmp + 1;
131
get_table_structure -- retrievs database structure, prints out corresponding
132
CREATE statement and fills out insert_pat if the table is the type we will
134
@@ -2480,6 +2561,9 @@
136
row= mysql_fetch_row(result);
138
+ if (opt_innodb_optimize_keys && !strcmp(table_type, "InnoDB"))
139
+ skip_secondary_keys(row[1]);
141
fprintf(sql_file, (opt_compatible_mode & 3) ? "%s;\n" :
142
"/*!40101 SET @saved_cs_client = @@character_set_client */;\n"
143
"/*!40101 SET character_set_client = utf8 */;\n"
144
@@ -3572,6 +3656,27 @@
148
+ /* Perform delayed secondary index creation for --innodb-optimize-keys */
149
+ if (skipped_keys_list)
152
+ skipped_keys_list= list_reverse(skipped_keys_list);
153
+ fprintf(md_result_file, "ALTER TABLE %s ", opt_quoted_table);
154
+ for (keys= list_length(skipped_keys_list); keys > 0; keys--)
156
+ LIST *node= skipped_keys_list;
157
+ char *def= node->data;
159
+ fprintf(md_result_file, "ADD %s%s", def, (keys > 1) ? ", " : ";\n");
161
+ skipped_keys_list= list_delete(skipped_keys_list, node);
162
+ my_free(def, MYF(0));
163
+ my_free(node, MYF(0));
166
+ DBUG_ASSERT(skipped_keys_list == NULL);
169
/* Moved enable keys to before unlock per bug 15977 */
170
if (opt_disable_keys)
172
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
173
+++ b/mysql-test/r/percona_mysqldump_innodb_optimize_keys.result 2011-03-31 12:05:39.000000000 +0400
176
+# Test the --innodb-optimize-keys option.
178
+CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b INT, KEY(b)) ENGINE=MyISAM;
179
+######################################
181
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
182
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
183
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
184
+/*!40101 SET NAMES utf8 */;
185
+/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
186
+/*!40103 SET TIME_ZONE='+00:00' */;
187
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
188
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
189
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
190
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
191
+DROP TABLE IF EXISTS `t1`;
192
+/*!40101 SET @saved_cs_client = @@character_set_client */;
193
+/*!40101 SET character_set_client = utf8 */;
195
+ `a` int(11) NOT NULL,
196
+ `b` int(11) DEFAULT NULL,
199
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
200
+/*!40101 SET character_set_client = @saved_cs_client */;
202
+LOCK TABLES `t1` WRITE;
203
+/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
204
+/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
206
+/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
208
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
209
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
210
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
211
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
212
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
213
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
214
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
216
+######################################
218
+CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB;
219
+INSERT INTO t2 VALUES (0), (1), (2);
221
+id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
222
+a INT, b VARCHAR(255), c DECIMAL(10,3),
224
+UNIQUE KEY uniq(c,a),
225
+FOREIGN KEY (a) REFERENCES t2(a) ON DELETE CASCADE
227
+INSERT INTO t1(a,b,c) VALUES (0, "0", 0.0), (1, "1", 1.1), (2, "2", 2.2);
228
+######################################
230
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
231
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
232
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
233
+/*!40101 SET NAMES utf8 */;
234
+/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
235
+/*!40103 SET TIME_ZONE='+00:00' */;
236
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
237
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
238
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
239
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
240
+DROP TABLE IF EXISTS `t1`;
241
+/*!40101 SET @saved_cs_client = @@character_set_client */;
242
+/*!40101 SET character_set_client = utf8 */;
244
+ `id` int(11) NOT NULL AUTO_INCREMENT,
245
+ `a` int(11) DEFAULT NULL,
246
+ `b` varchar(255) DEFAULT NULL,
247
+ `c` decimal(10,3) DEFAULT NULL,
249
+) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;
250
+/*!40101 SET character_set_client = @saved_cs_client */;
252
+LOCK TABLES `t1` WRITE;
253
+/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
254
+INSERT INTO `t1` VALUES (1,0,'0','0.000'),(2,1,'1','1.100'),(3,2,'2','2.200');
255
+ALTER TABLE `t1` ADD UNIQUE KEY `uniq` (`c`,`a`), ADD KEY `b` (`b`), ADD KEY `a` (`a`), ADD CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t2` (`a`) ON DELETE CASCADE;
256
+/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
258
+DROP TABLE IF EXISTS `t2`;
259
+/*!40101 SET @saved_cs_client = @@character_set_client */;
260
+/*!40101 SET character_set_client = utf8 */;
262
+ `a` int(11) NOT NULL,
264
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
265
+/*!40101 SET character_set_client = @saved_cs_client */;
267
+LOCK TABLES `t2` WRITE;
268
+/*!40000 ALTER TABLE `t2` DISABLE KEYS */;
269
+INSERT INTO `t2` VALUES (0),(1),(2);
270
+/*!40000 ALTER TABLE `t2` ENABLE KEYS */;
272
+/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
274
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
275
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
276
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
277
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
278
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
279
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
280
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
282
+######################################
284
--- a/mysql-test/suite/innodb_plugin/r/innodb.result 2011-03-31 12:04:33.000000000 +0400
285
+++ b/mysql-test/suite/innodb_plugin/r/innodb.result 2011-03-31 12:05:39.000000000 +0400
286
@@ -1679,7 +1679,7 @@
288
SELECT variable_value - @innodb_rows_inserted_orig FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_rows_inserted';
289
variable_value - @innodb_rows_inserted_orig
292
SELECT variable_value - @innodb_rows_updated_orig FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_rows_updated';
293
variable_value - @innodb_rows_updated_orig
295
--- a/mysql-test/suite/innodb_plugin/t/innodb-index.test 2011-02-11 22:49:34.000000000 +0300
296
+++ b/mysql-test/suite/innodb_plugin/t/innodb-index.test 2011-03-31 12:05:39.000000000 +0400
298
show create table t1;
299
--error ER_MULTIPLE_PRI_KEY
300
alter table t1 add primary key (c);
301
+# Suppress the error log messages occuring on duplicate key error
302
+# during ALTER TABLE when using fast index creation
304
+call mtr.add_suppression("Cannot find index PRIMARY in InnoDB index translation table.");
307
alter table t1 drop primary key, add primary key (b);
308
create unique index c on t1 (c);
309
--- a/mysql-test/suite/innodb_plugin/t/innodb.test 2011-02-11 22:49:35.000000000 +0300
310
+++ b/mysql-test/suite/innodb_plugin/t/innodb.test 2011-03-31 12:05:39.000000000 +0400
313
-- source include/have_innodb_plugin.inc
315
+# Suppress the error log message occuring on duplicate key error
316
+# during ALTER TABLE when using fast index creation
318
+call mtr.add_suppression("Cannot find index v_2 in InnoDB index translation table.");
321
let $MYSQLD_DATADIR= `select @@datadir`;
323
# Save the original values of some variables in order to be able to
324
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
325
+++ b/mysql-test/t/percona_mysqldump_innodb_optimize_keys.test 2011-03-31 12:05:39.000000000 +0400
327
+# Embedded server doesn't support external clients
328
+--source include/not_embedded.inc
330
+# Fast index creation is only available in InnoDB plugin
331
+--source include/have_innodb_plugin.inc
333
+# Save the initial number of concurrent sessions
334
+--source include/count_sessions.inc
337
+--echo # Test the --innodb-optimize-keys option.
340
+--let $file=$MYSQLTEST_VARDIR/tmp/t1.sql
342
+# First test that the option has no effect on non-InnoDB tables
344
+CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b INT, KEY(b)) ENGINE=MyISAM;
346
+--exec $MYSQL_DUMP --skip-comments --innodb-optimize-keys test t1 >$file
348
+--echo ######################################
350
+--echo ######################################
357
+# Check that for InnoDB tables secondary and foreign keys are created
358
+# after the data is dumped
360
+CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB;
361
+INSERT INTO t2 VALUES (0), (1), (2);
364
+ id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
365
+ a INT, b VARCHAR(255), c DECIMAL(10,3),
367
+ UNIQUE KEY uniq(c,a),
368
+ FOREIGN KEY (a) REFERENCES t2(a) ON DELETE CASCADE
371
+INSERT INTO t1(a,b,c) VALUES (0, "0", 0.0), (1, "1", 1.1), (2, "2", 2.2);
373
+--exec $MYSQL_DUMP --skip-comments --innodb-optimize-keys test t1 t2 >$file
375
+--echo ######################################
377
+--echo ######################################
379
+# Check that the resulting dump can be imported back
381
+--exec $MYSQL test < $file
387
+# Wait till we reached the initial number of concurrent sessions
388
+--source include/wait_until_count_sessions.inc
389
--- a/sql/sql_lex.cc 2011-03-31 12:04:37.000000000 +0400
390
+++ b/sql/sql_lex.cc 2011-03-31 12:13:39.000000000 +0400
391
@@ -1494,6 +1494,9 @@
392
alter_list(rhs.alter_list, mem_root),
393
key_list(rhs.key_list, mem_root),
394
create_list(rhs.create_list, mem_root),
395
+ delayed_key_list(rhs.delayed_key_list, mem_root),
396
+ delayed_key_info(rhs.delayed_key_info),
397
+ delayed_key_count(rhs.delayed_key_count),
399
keys_onoff(rhs.keys_onoff),
400
tablespace_op(rhs.tablespace_op),
401
@@ -1516,6 +1519,7 @@
402
list_copy_and_replace_each_value(alter_list, mem_root);
403
list_copy_and_replace_each_value(key_list, mem_root);
404
list_copy_and_replace_each_value(create_list, mem_root);
405
+ list_copy_and_replace_each_value(delayed_key_list, mem_root);
406
/* partition_names are not deeply copied currently */
409
--- a/sql/sql_lex.h 2011-03-31 12:04:38.000000000 +0400
410
+++ b/sql/sql_lex.h 2011-03-31 12:14:36.000000000 +0400
412
List<Alter_column> alter_list;
414
List<Create_field> create_list;
415
+ List<Key> delayed_key_list;
416
+ KEY *delayed_key_info;
417
+ uint delayed_key_count;
419
enum enum_enable_or_disable keys_onoff;
420
enum tablespace_op_type tablespace_op;
425
+ delayed_key_info(NULL),
426
+ delayed_key_count(0),
428
keys_onoff(LEAVE_AS_IS),
429
tablespace_op(NO_TABLESPACE_OP),
434
+ delayed_key_list.empty();
435
+ delayed_key_info= NULL;
436
+ delayed_key_count= 0;
438
keys_onoff= LEAVE_AS_IS;
439
tablespace_op= NO_TABLESPACE_OP;
440
--- a/sql/sql_table.cc 2011-03-31 12:04:35.000000000 +0400
441
+++ b/sql/sql_table.cc 2011-03-31 12:05:39.000000000 +0400
442
@@ -2558,7 +2558,7 @@
443
file The handler for the new table.
444
key_info_buffer OUT An array of KEY structs for the indexes.
445
key_count OUT The number of elements in the array.
446
- select_field_count The number of fields coming from a select table.
447
+ select_field_count The number of fields coming from a select table.
450
Prepares the table and key structures for table creation.
451
@@ -2913,7 +2913,6 @@
456
List_iterator<Key> key_iterator(alter_info->key_list);
457
List_iterator<Key> key_iterator2(alter_info->key_list);
458
uint key_parts=0, fk_key_count=0;
459
@@ -3013,6 +3012,14 @@
460
if (!*key_info_buffer || ! key_part_info)
461
DBUG_RETURN(TRUE); // Out of memory
463
+ List_iterator<Key> delayed_key_iterator(alter_info->delayed_key_list);
464
+ alter_info->delayed_key_count= 0;
465
+ if (alter_info->delayed_key_list.elements > 0)
467
+ alter_info->delayed_key_info= (KEY *) sql_calloc(sizeof(KEY) *
471
key_iterator.rewind();
473
for (; (key=key_iterator++) ; key_number++)
474
@@ -3382,8 +3389,26 @@
475
my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
479
+ if (alter_info->delayed_key_list.elements > 0)
483
+ delayed_key_iterator.rewind();
484
+ while ((delayed_key= delayed_key_iterator++))
486
+ if (delayed_key == key)
488
+ alter_info->delayed_key_info[alter_info->delayed_key_count++]=
498
if (!unique_key && !primary_key &&
499
(file->ha_table_flags() & HA_REQUIRE_PRIMARY_KEY))
501
@@ -6081,6 +6106,10 @@
502
List<Create_field> new_create_list;
503
/* New key definitions are added here */
504
List<Key> new_key_list;
505
+ /* List with secondary keys which should be created after copying the data */
506
+ List<Key> delayed_key_list;
507
+ /* Foreign key list returned by handler::get_foreign_key_list() */
508
+ List<FOREIGN_KEY_INFO> f_key_list;
509
List_iterator<Alter_drop> drop_it(alter_info->drop_list);
510
List_iterator<Create_field> def_it(alter_info->create_list);
511
List_iterator<Alter_column> alter_it(alter_info->alter_list);
512
@@ -6093,6 +6122,7 @@
513
uint used_fields= create_info->used_fields;
514
KEY *key_info=table->key_info;
516
+ bool skip_secondary;
518
DBUG_ENTER("mysql_prepare_alter_table");
520
@@ -6120,6 +6150,7 @@
521
char *tablespace= static_cast<char *>(thd->alloc(FN_LEN + 1));
523
Regular alter table of disk stored table (no tablespace/storage change)
528
@@ -6270,7 +6301,23 @@
530
Collect all keys which isn't in drop list. Add only those
531
for which some fields exists.
534
+ We also skip secondary keys for InnoDB tables and store them in
535
+ delayed_key_list to create them later after copying the data to make use of
536
+ the InnoDB fast index creation. The following conditions must be met:
538
+ - we are going to create an InnoDB table;
539
+ - the key most be a non-UNIQUE one;
540
+ - there are no foreign keys. This can be optimized later to exclude only
541
+ those keys which are a part of foreign key constraints. Currently we
542
+ simply disable this optimization for all keys if there are any foreign
543
+ key constraints in the table.
547
+ !my_strcasecmp(system_charset_info, table->file->table_type(), "InnoDB") &&
548
+ !table->file->get_foreign_key_list(thd, &f_key_list) &&
549
+ f_key_list.elements == 0;
551
for (uint i=0 ; i < table->s->keys ; i++,key_info++)
553
@@ -6373,6 +6420,8 @@
554
test(key_info->flags & HA_GENERATED_KEY),
556
new_key_list.push_back(key);
557
+ if (skip_secondary && key_type == Key::MULTIPLE)
558
+ delayed_key_list.push_back(key);
562
@@ -6380,7 +6429,21 @@
563
while ((key=key_it++)) // Add new keys
565
if (key->type != Key::FOREIGN_KEY)
566
- new_key_list.push_back(key);
568
+ new_key_list.push_back(key);
569
+ if (skip_secondary && key->type == Key::MULTIPLE)
570
+ delayed_key_list.push_back(key);
572
+ else if (skip_secondary)
575
+ We are adding a foreign key so disable the secondary keys
578
+ skip_secondary= FALSE;
579
+ delayed_key_list.empty();
583
!my_strcasecmp(system_charset_info,key->name,primary_key_name))
585
@@ -6429,12 +6492,100 @@
587
alter_info->create_list.swap(new_create_list);
588
alter_info->key_list.swap(new_key_list);
589
+ alter_info->delayed_key_list.swap(delayed_key_list);
596
+ Temporarily remove secondary keys previously stored in
597
+ alter_info->delayed_key_info.
600
+remove_secondary_keys(THD *thd, TABLE *table, Alter_info *alter_info)
603
+ uint key_counter= 0;
606
+ DBUG_ENTER("remove_secondary_keys");
607
+ DBUG_ASSERT(alter_info->delayed_key_count > 0);
609
+ key_numbers= (uint *) thd->alloc(sizeof(uint) *
610
+ alter_info->delayed_key_count);
611
+ for (i= 0; i < alter_info->delayed_key_count; i++)
613
+ KEY *key= alter_info->delayed_key_info + i;
616
+ for (j= 0; j < table->s->keys; j++)
618
+ if (!strcmp(table->key_info[j].name, key->name))
620
+ key_numbers[key_counter++]= j;
626
+ DBUG_ASSERT(key_counter == alter_info->delayed_key_count);
628
+ if ((error= table->file->prepare_drop_index(table, key_numbers,
630
+ (error= table->file->final_drop_index(table)))
632
+ table->file->print_error(error, MYF(0));
635
+ DBUG_RETURN(error);
639
+ Restore secondary keys previously removed in remove_secondary_keys.
643
+restore_secondary_keys(THD *thd, TABLE *table, Alter_info *alter_info)
647
+ DBUG_ENTER("restore_secondary_keys");
648
+ DBUG_ASSERT(alter_info->delayed_key_count > 0);
650
+ thd_proc_info(thd, "restoring secondary keys");
652
+ /* Fix the key parts */
653
+ for (i= 0; i < alter_info->delayed_key_count; i++)
655
+ KEY *key = alter_info->delayed_key_info + i;
656
+ KEY_PART_INFO *key_part;
657
+ KEY_PART_INFO *part_end;
659
+ part_end= key->key_part + key->key_parts;
660
+ for (key_part= key->key_part; key_part < part_end; key_part++)
661
+ key_part->field= table->field[key_part->fieldnr];
664
+ if ((error= table->file->add_index(table, alter_info->delayed_key_info,
665
+ alter_info->delayed_key_count)))
668
+ Exchange the key_info for the error message. If we exchange
669
+ key number by key name in the message later, we need correct info.
671
+ KEY *save_key_info= table->key_info;
672
+ table->key_info= alter_info->delayed_key_info;
673
+ table->file->print_error(error, MYF(0));
674
+ table->key_info= save_key_info;
676
+ DBUG_RETURN(error);
686
@@ -7218,6 +7369,12 @@
688
create_info->data_file_name=create_info->index_file_name=0;
691
+ Postpone secondary index creation for InnoDB tables if the data has to be
693
+ TODO: is there a better way to check for InnoDB?
696
DEBUG_SYNC(thd, "alter_table_before_create_table_no_lock");
698
Create a table with a temporary name.
699
@@ -7277,12 +7434,21 @@
700
/* We don't want update TIMESTAMP fields during ALTER TABLE. */
701
new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
702
new_table->next_number_field=new_table->found_next_number_field;
704
+ if (alter_info->delayed_key_count > 0)
706
+ /* ignore the error */
707
+ error= remove_secondary_keys(thd, new_table, alter_info);
710
thd_proc_info(thd, "copy to tmp table");
711
error= copy_data_between_tables(table, new_table,
712
alter_info->create_list, ignore,
713
order_num, order, &copied, &deleted,
714
alter_info->keys_onoff,
715
alter_info->error_if_not_empty);
716
+ if (!error && alter_info->delayed_key_count > 0)
717
+ error= restore_secondary_keys(thd, new_table, alter_info);