Skip to content

Commit e2afa05

Browse files
author
Satya B
committed
Applying InnoDB snapshot 5.0-ss6230, part 2. Fixes BUG#46000
BUG#46000 - using index called GEN_CLUST_INDEX crashes server Detailed revision comments: r6180 | jyang | 2009-11-17 10:54:57 +0200 (Tue, 17 Nov 2009) | 7 lines branches/5.0: Merge/Port fix for bug #46000 from branches/5.1 -r5895 to branches/5.0. Disallow creating index with the name of "GEN_CLUST_INDEX" which is reserved for the default system primary index. Minor adjusts on table name screening format for added tests.
1 parent 0dd5eaa commit e2afa05

File tree

3 files changed

+127
-14
lines changed

3 files changed

+127
-14
lines changed

mysql-test/r/innodb_bug46000.result

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
create table bug46000(`id` int,key `GEN_CLUST_INDEX`(`id`))engine=innodb;
2+
ERROR HY000: Can't create table bug46000.frm' (errno: -1)
3+
show warnings;
4+
Level Code Message
5+
Warning 1005 Cannot Create Index with name 'GEN_CLUST_INDEX'. The name is reserved for the system default primary index.
6+
Error 1005 Can't create table bug46000.frm' (errno: -1)
7+
create table bug46000(`id` int, key `GEN_clust_INDEX`(`id`))engine=innodb;
8+
ERROR HY000: Can't create table bug46000.frm' (errno: -1)
9+
create table bug46000(id int) engine=innodb;
10+
create index GEN_CLUST_INDEX on bug46000(id);
11+
ERROR HY000: Can't create table #sql-temporary' (errno: -1)
12+
create index idx on bug46000(id);
13+
drop table bug46000;

mysql-test/t/innodb_bug46000.test

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# This is the test for bug 46000. We shall
2+
# block any index creation with the name of
3+
# "GEN_CLUST_INDEX", which is the reserved
4+
# name for innodb default primary index.
5+
6+
--source include/have_innodb.inc
7+
8+
# This 'create table' operation should fail because of
9+
# using the reserve name as its index name.
10+
--replace_regex /'[^']*test\///
11+
--error ER_CANT_CREATE_TABLE
12+
create table bug46000(`id` int,key `GEN_CLUST_INDEX`(`id`))engine=innodb;
13+
14+
--replace_regex /'[^']*test\///
15+
show warnings;
16+
17+
# Mixed upper/lower case of the reserved key words
18+
--replace_regex /'[^']*test\///
19+
--error ER_CANT_CREATE_TABLE
20+
create table bug46000(`id` int, key `GEN_clust_INDEX`(`id`))engine=innodb;
21+
22+
create table bug46000(id int) engine=innodb;
23+
24+
# This 'create index' operation should fail.
25+
--replace_regex /'[^']*test\/#sql-[0-9a-f_]*.frm/#sql-temporary/
26+
--error ER_CANT_CREATE_TABLE
27+
create index GEN_CLUST_INDEX on bug46000(id);
28+
29+
# This 'create index' operation should succeed, no
30+
# temp table left from last failed create index
31+
# operation.
32+
create index idx on bug46000(id);
33+
34+
drop table bug46000;

sql/ha_innodb.cc

Lines changed: 80 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,24 @@ handlerton innobase_hton = {
226226
innobase_close_cursor_view,
227227
HTON_NO_FLAGS
228228
};
229+
/***********************************************************************
230+
This function checks each index name for a table against reserved
231+
system default primary index name 'GEN_CLUST_INDEX'. If a name matches,
232+
this function pushes an error message to the client, and returns true. */
233+
static
234+
bool
235+
innobase_index_name_is_reserved(
236+
/*============================*/
237+
/* out: true if index name matches a
238+
reserved name */
239+
const trx_t* trx, /* in: InnoDB transaction handle */
240+
const TABLE* form, /* in: information on table
241+
columns and indexes */
242+
const char* norm_name); /* in: table name */
243+
244+
/* "GEN_CLUST_INDEX" is the name reserved for Innodb default
245+
system primary index. */
246+
static const char innobase_index_reserve_name[]= "GEN_CLUST_INDEX";
229247

230248
/*********************************************************************
231249
Commits a transaction in an InnoDB database. */
@@ -4496,7 +4514,10 @@ create_index(
44964514

44974515
n_fields = key->key_parts;
44984516

4499-
ind_type = 0;
4517+
/* Assert that "GEN_CLUST_INDEX" cannot be used as non-primary index */
4518+
ut_a(innobase_strcasecmp(key->name, innobase_index_reserve_name) != 0);
4519+
4520+
ind_type = 0;
45004521

45014522
if (key_num == form->s->primary_key) {
45024523
ind_type = ind_type | DICT_CLUSTERED;
@@ -4606,9 +4627,8 @@ create_clustered_index_when_no_primary(
46064627

46074628
/* We pass 0 as the space id, and determine at a lower level the space
46084629
id where to store the table */
4609-
4610-
index = dict_mem_index_create((char*) table_name,
4611-
(char*) "GEN_CLUST_INDEX",
4630+
index = dict_mem_index_create(table_name,
4631+
innobase_index_reserve_name,
46124632
0, DICT_CLUSTERED, 0);
46134633
error = row_create_index_for_mysql(index, trx, NULL);
46144634

@@ -4706,16 +4726,6 @@ ha_innobase::create(
47064726

47074727
row_mysql_lock_data_dictionary(trx);
47084728

4709-
/* Create the table definition in InnoDB */
4710-
4711-
error = create_table_def(trx, form, norm_name,
4712-
create_info->options & HA_LEX_CREATE_TMP_TABLE ? name2 : NULL,
4713-
form->s->row_type != ROW_TYPE_REDUNDANT);
4714-
4715-
if (error) {
4716-
goto cleanup;
4717-
}
4718-
47194729
/* Look for a primary key */
47204730

47214731
primary_key_no= (table->s->primary_key != MAX_KEY ?
@@ -4727,6 +4737,23 @@ ha_innobase::create(
47274737

47284738
DBUG_ASSERT(primary_key_no == -1 || primary_key_no == 0);
47294739

4740+
/* Check for name conflicts (with reserved name) for
4741+
any user indices to be created. */
4742+
if (innobase_index_name_is_reserved(trx, form, norm_name)) {
4743+
error = -1;
4744+
goto cleanup;
4745+
}
4746+
4747+
/* Create the table definition in InnoDB */
4748+
error = create_table_def(trx, form, norm_name,
4749+
create_info->options & HA_LEX_CREATE_TMP_TABLE ? name2 : NULL,
4750+
form->s->row_type != ROW_TYPE_REDUNDANT);
4751+
4752+
if (error) {
4753+
goto cleanup;
4754+
}
4755+
4756+
47304757
/* Create the keys */
47314758

47324759
if (form->s->keys == 0 || primary_key_no == -1) {
@@ -7431,4 +7458,43 @@ innobase_set_cursor_view(
74317458
(cursor_view_t*) curview);
74327459
}
74337460

7461+
/***********************************************************************
7462+
This function checks each index name for a table against reserved
7463+
system default primary index name 'GEN_CLUST_INDEX'. If a name matches,
7464+
this function pushes an error message to the client, and returns true. */
7465+
static
7466+
bool
7467+
innobase_index_name_is_reserved(
7468+
/*============================*/
7469+
/* out: true if an index name
7470+
matches the reserved name */
7471+
const trx_t* trx, /* in: InnoDB transaction handle */
7472+
const TABLE* form, /* in: information on table
7473+
columns and indexes */
7474+
const char* norm_name) /* in: table name */
7475+
{
7476+
KEY* key;
7477+
uint key_num; /* index number */
7478+
7479+
for (key_num = 0; key_num < form->s->keys; key_num++) {
7480+
key = form->key_info + key_num;
7481+
7482+
if (innobase_strcasecmp(key->name,
7483+
innobase_index_reserve_name) == 0) {
7484+
/* Push warning to mysql */
7485+
push_warning_printf((THD*) trx->mysql_thd,
7486+
MYSQL_ERROR::WARN_LEVEL_WARN,
7487+
ER_CANT_CREATE_TABLE,
7488+
"Cannot Create Index with name "
7489+
"'%s'. The name is reserved "
7490+
"for the system default primary "
7491+
"index.",
7492+
innobase_index_reserve_name);
7493+
7494+
return(true);
7495+
}
7496+
}
7497+
7498+
return(false);
7499+
}
74347500
#endif /* HAVE_INNOBASE_DB */

0 commit comments

Comments
 (0)