#At file:///home/satya/WORK/mysql/mysql-5.0-bugteam/ based on revid:satya.bn@stripped
2852 Satya B 2009-11-25
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.
added:
mysql-test/r/innodb_bug46000.result
mysql-test/t/innodb_bug46000.test
modified:
sql/ha_innodb.cc
=== added file 'mysql-test/r/innodb_bug46000.result'
--- a/mysql-test/r/innodb_bug46000.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/innodb_bug46000.result 2009-11-25 09:59:25 +0000
@@ -0,0 +1,13 @@
+create table bug46000(`id` int,key `GEN_CLUST_INDEX`(`id`))engine=innodb;
+ERROR HY000: Can't create table bug46000.frm' (errno: -1)
+show warnings;
+Level Code Message
+Warning 1005 Cannot Create Index with name 'GEN_CLUST_INDEX'. The name is reserved for the system default primary index.
+Error 1005 Can't create table bug46000.frm' (errno: -1)
+create table bug46000(`id` int, key `GEN_clust_INDEX`(`id`))engine=innodb;
+ERROR HY000: Can't create table bug46000.frm' (errno: -1)
+create table bug46000(id int) engine=innodb;
+create index GEN_CLUST_INDEX on bug46000(id);
+ERROR HY000: Can't create table #sql-temporary' (errno: -1)
+create index idx on bug46000(id);
+drop table bug46000;
=== added file 'mysql-test/t/innodb_bug46000.test'
--- a/mysql-test/t/innodb_bug46000.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/innodb_bug46000.test 2009-11-25 09:59:25 +0000
@@ -0,0 +1,34 @@
+# This is the test for bug 46000. We shall
+# block any index creation with the name of
+# "GEN_CLUST_INDEX", which is the reserved
+# name for innodb default primary index.
+
+--source include/have_innodb.inc
+
+# This 'create table' operation should fail because of
+# using the reserve name as its index name.
+--replace_regex /'[^']*test\///
+--error ER_CANT_CREATE_TABLE
+create table bug46000(`id` int,key `GEN_CLUST_INDEX`(`id`))engine=innodb;
+
+--replace_regex /'[^']*test\///
+show warnings;
+
+# Mixed upper/lower case of the reserved key words
+--replace_regex /'[^']*test\///
+--error ER_CANT_CREATE_TABLE
+create table bug46000(`id` int, key `GEN_clust_INDEX`(`id`))engine=innodb;
+
+create table bug46000(id int) engine=innodb;
+
+# This 'create index' operation should fail.
+--replace_regex /'[^']*test\/#sql-[0-9a-f_]*.frm/#sql-temporary/
+--error ER_CANT_CREATE_TABLE
+create index GEN_CLUST_INDEX on bug46000(id);
+
+# This 'create index' operation should succeed, no
+# temp table left from last failed create index
+# operation.
+create index idx on bug46000(id);
+
+drop table bug46000;
=== modified file 'sql/ha_innodb.cc'
--- a/sql/ha_innodb.cc 2009-11-25 09:38:52 +0000
+++ b/sql/ha_innodb.cc 2009-11-25 09:59:25 +0000
@@ -226,6 +226,24 @@ handlerton innobase_hton = {
innobase_close_cursor_view,
HTON_NO_FLAGS
};
+/***********************************************************************
+This function checks each index name for a table against reserved
+system default primary index name 'GEN_CLUST_INDEX'. If a name matches,
+this function pushes an error message to the client, and returns true. */
+static
+bool
+innobase_index_name_is_reserved(
+/*============================*/
+ /* out: true if index name matches a
+ reserved name */
+ const trx_t* trx, /* in: InnoDB transaction handle */
+ const TABLE* form, /* in: information on table
+ columns and indexes */
+ const char* norm_name); /* in: table name */
+
+/* "GEN_CLUST_INDEX" is the name reserved for Innodb default
+system primary index. */
+static const char innobase_index_reserve_name[]= "GEN_CLUST_INDEX";
/*********************************************************************
Commits a transaction in an InnoDB database. */
@@ -4496,7 +4514,10 @@ create_index(
n_fields = key->key_parts;
- ind_type = 0;
+ /* Assert that "GEN_CLUST_INDEX" cannot be used as non-primary index */
+ ut_a(innobase_strcasecmp(key->name, innobase_index_reserve_name) != 0);
+
+ ind_type = 0;
if (key_num == form->s->primary_key) {
ind_type = ind_type | DICT_CLUSTERED;
@@ -4606,9 +4627,8 @@ create_clustered_index_when_no_primary(
/* We pass 0 as the space id, and determine at a lower level the space
id where to store the table */
-
- index = dict_mem_index_create((char*) table_name,
- (char*) "GEN_CLUST_INDEX",
+ index = dict_mem_index_create(table_name,
+ innobase_index_reserve_name,
0, DICT_CLUSTERED, 0);
error = row_create_index_for_mysql(index, trx, NULL);
@@ -4706,16 +4726,6 @@ ha_innobase::create(
row_mysql_lock_data_dictionary(trx);
- /* Create the table definition in InnoDB */
-
- error = create_table_def(trx, form, norm_name,
- create_info->options & HA_LEX_CREATE_TMP_TABLE ? name2 : NULL,
- form->s->row_type != ROW_TYPE_REDUNDANT);
-
- if (error) {
- goto cleanup;
- }
-
/* Look for a primary key */
primary_key_no= (table->s->primary_key != MAX_KEY ?
@@ -4727,6 +4737,23 @@ ha_innobase::create(
DBUG_ASSERT(primary_key_no == -1 || primary_key_no == 0);
+ /* Check for name conflicts (with reserved name) for
+ any user indices to be created. */
+ if (innobase_index_name_is_reserved(trx, form, norm_name)) {
+ error = -1;
+ goto cleanup;
+ }
+
+ /* Create the table definition in InnoDB */
+ error = create_table_def(trx, form, norm_name,
+ create_info->options & HA_LEX_CREATE_TMP_TABLE ? name2 : NULL,
+ form->s->row_type != ROW_TYPE_REDUNDANT);
+
+ if (error) {
+ goto cleanup;
+ }
+
+
/* Create the keys */
if (form->s->keys == 0 || primary_key_no == -1) {
@@ -7431,4 +7458,43 @@ innobase_set_cursor_view(
(cursor_view_t*) curview);
}
+/***********************************************************************
+This function checks each index name for a table against reserved
+system default primary index name 'GEN_CLUST_INDEX'. If a name matches,
+this function pushes an error message to the client, and returns true. */
+static
+bool
+innobase_index_name_is_reserved(
+/*============================*/
+ /* out: true if an index name
+ matches the reserved name */
+ const trx_t* trx, /* in: InnoDB transaction handle */
+ const TABLE* form, /* in: information on table
+ columns and indexes */
+ const char* norm_name) /* in: table name */
+{
+ KEY* key;
+ uint key_num; /* index number */
+
+ for (key_num = 0; key_num < form->s->keys; key_num++) {
+ key = form->key_info + key_num;
+
+ if (innobase_strcasecmp(key->name,
+ innobase_index_reserve_name) == 0) {
+ /* Push warning to mysql */
+ push_warning_printf((THD*) trx->mysql_thd,
+ MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_CANT_CREATE_TABLE,
+ "Cannot Create Index with name "
+ "'%s'. The name is reserved "
+ "for the system default primary "
+ "index.",
+ innobase_index_reserve_name);
+
+ return(true);
+ }
+ }
+
+ return(false);
+}
#endif /* HAVE_INNOBASE_DB */
Attachment: [text/bzr-bundle] bzr/satya.bn@sun.com-20091125095925-871384fcnwwa2yqt.bundle
| Thread |
|---|
| • bzr commit into mysql-5.0-bugteam branch (satya.bn:2852) Bug#46000 | Satya B | 25 Nov |