Commit 66f6a5ac authored by marko's avatar marko

branches/zip: Fix bugs in the creation or dropping of the clustered index

(PRIMARY KEY or UNIQUE INDEX on NOT NULL columns).

innodb-index.test: Remove the --replace_regex directives.  Replace correct
values to the "Duplicate entry" messages.  This will cause the test to
fail until we somehow return the duplicate key values to MySQL.
Add test cases for creating or dropping UNIQUE INDEX or PRIMARY KEY.

innobase_copy_index_def(): Allow the function to copy a clustered index
definition to a secondary one (UNIQUE INDEX).

innobase_create_key_def(): Check the NOT NULL flag from the correct
place.  Copy the clustered index if it is a UNIQUE INDEX.

ha_innobase::prepare_drop_index(): Refuse to drop the clustered index.
parent c541324b
...@@ -8143,11 +8143,9 @@ innobase_copy_index_def( ...@@ -8143,11 +8143,9 @@ innobase_copy_index_def(
ulint i; ulint i;
DBUG_ENTER("innobase_copy_index_def"); DBUG_ENTER("innobase_copy_index_def");
DBUG_ASSERT(!dict_index_is_clust(index));
/* Note that from the secondary index we take only /* Note that we take only those fields that user defined to be
those fields that user defined to be in the index. in the index. In the internal representation more colums were
In the internal representation more colums were
added and those colums are not copied .*/ added and those colums are not copied .*/
n_fields = index->n_user_defined_cols; n_fields = index->n_user_defined_cols;
...@@ -8155,7 +8153,9 @@ innobase_copy_index_def( ...@@ -8155,7 +8153,9 @@ innobase_copy_index_def(
new_index->fields = (merge_index_field_t*) mem_heap_alloc( new_index->fields = (merge_index_field_t*) mem_heap_alloc(
heap, n_fields * sizeof *new_index->fields); heap, n_fields * sizeof *new_index->fields);
new_index->ind_type = index->type; /* When adding a PRIMARY KEY, we may convert a previous
clustered index to a secondary index (UNIQUE NOT NULL). */
new_index->ind_type = index->type & ~DICT_CLUSTERED;
new_index->n_fields = n_fields; new_index->n_fields = n_fields;
new_index->name = index->name; new_index->name = index->name;
...@@ -8203,11 +8203,9 @@ innobase_create_key_def( ...@@ -8203,11 +8203,9 @@ innobase_create_key_def(
DBUG_ENTER("innobase_create_key_def"); DBUG_ENTER("innobase_create_key_def");
/* We do not need to count the original primary key */
const ulint n_indexes = n_keys + UT_LIST_GET_LEN(table->indexes) - 1;
indexdef = indexdefs = (merge_index_def_t*) indexdef = indexdefs = (merge_index_def_t*)
mem_heap_alloc(heap, sizeof *indexdef * n_indexes); mem_heap_alloc(heap, sizeof *indexdef
* (n_keys + UT_LIST_GET_LEN(table->indexes)));
/* If there is a primary key, it is always the first index /* If there is a primary key, it is always the first index
defined for the table. */ defined for the table. */
...@@ -8226,7 +8224,8 @@ innobase_create_key_def( ...@@ -8226,7 +8224,8 @@ innobase_create_key_def(
new_primary = TRUE; new_primary = TRUE;
while (key_part--) { while (key_part--) {
if (key_info->key_part[key_part].null_bit) { if (key_info->key_part[key_part].key_type
& FIELDFLAG_MAYBE_NULL) {
new_primary = FALSE; new_primary = FALSE;
break; break;
} }
...@@ -8237,21 +8236,25 @@ innobase_create_key_def( ...@@ -8237,21 +8236,25 @@ innobase_create_key_def(
const dict_index_t* index; const dict_index_t* index;
/* Create the PRIMARY key index definition */ /* Create the PRIMARY key index definition */
innobase_create_index_def(key_info, TRUE, TRUE, innobase_create_index_def(&key_info[i++], TRUE, TRUE,
indexdef++, heap); indexdef++, heap);
row_mysql_lock_data_dictionary(trx); row_mysql_lock_data_dictionary(trx);
/* Skip the clustered index */ index = dict_table_get_first_index(table);
i = 1; /* Copy the index definitions of the old table. Skip
index = dict_table_get_next_index( the old clustered index if it is a generated clustered
dict_table_get_first_index(table)); index or a PRIMARY KEY. If the clustered index is a
UNIQUE INDEX, it must be converted to a secondary index. */
/* Copy the definitions of secondary indexes */ if (dict_index_get_nth_col(index, 0)->mtype == DATA_SYS
|| !my_strcasecmp(system_charset_info,
index->name, "PRIMARY")) {
index = dict_table_get_next_index(index);
}
while (index) { while (index) {
innobase_copy_index_def(index, indexdef++, heap); innobase_copy_index_def(index, indexdef++, heap);
index = dict_table_get_next_index(index); index = dict_table_get_next_index(index);
} }
...@@ -8628,6 +8631,17 @@ ha_innobase::prepare_drop_index( ...@@ -8628,6 +8631,17 @@ ha_innobase::prepare_drop_index(
goto func_exit; goto func_exit;
} }
/* Refuse to drop the clustered index. It would be
better to automatically generate a clustered index,
but mysql_alter_table() will call this method only
after ha_innobase::add_index(). */
if (dict_index_is_clust(index)) {
my_error(ER_REQUIRES_PRIMARY_KEY, MYF(0));
err = -1;
goto func_exit;
}
index->to_be_dropped = TRUE; index->to_be_dropped = TRUE;
} }
......
create table t1(a int not null, b int, c char(10), d varchar(20), primary key (a)) engine = innodb; create table t1(a int not null, b int, c char(10) not null, d varchar(20)) engine = innodb;
insert into t1 values (5,5,'oo','oo'),(4,4,'tr','tr'),(3,4,'ad','ad'),(2,3,'ak','ak'); insert into t1 values (5,5,'oo','oo'),(4,4,'tr','tr'),(3,4,'ad','ad'),(2,3,'ak','ak');
commit; commit;
alter table t1 add index b (b), add index b (b); alter table t1 add index b (b), add index b (b);
...@@ -11,9 +11,8 @@ Table Create Table ...@@ -11,9 +11,8 @@ Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL, `a` int(11) NOT NULL,
`b` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL,
`c` char(10) DEFAULT NULL, `c` char(10) NOT NULL,
`d` varchar(20) DEFAULT NULL, `d` varchar(20) DEFAULT NULL,
PRIMARY KEY (`a`),
KEY `d2` (`d`) KEY `d2` (`d`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ) ENGINE=InnoDB DEFAULT CHARSET=latin1
explain select * from t1 order by d; explain select * from t1 order by d;
...@@ -26,15 +25,14 @@ a b c d ...@@ -26,15 +25,14 @@ a b c d
5 5 oo oo 5 5 oo oo
4 4 tr tr 4 4 tr tr
alter table t1 add unique index (b); alter table t1 add unique index (b);
ERROR 23000: Duplicate entry '0' for key 'b' ERROR 23000: Duplicate entry '4' for key 'b'
show create table t1; show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL, `a` int(11) NOT NULL,
`b` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL,
`c` char(10) DEFAULT NULL, `c` char(10) NOT NULL,
`d` varchar(20) DEFAULT NULL, `d` varchar(20) DEFAULT NULL,
PRIMARY KEY (`a`),
KEY `d2` (`d`) KEY `d2` (`d`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ) ENGINE=InnoDB DEFAULT CHARSET=latin1
alter table t1 add index (b); alter table t1 add index (b);
...@@ -43,9 +41,8 @@ Table Create Table ...@@ -43,9 +41,8 @@ Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL, `a` int(11) NOT NULL,
`b` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL,
`c` char(10) DEFAULT NULL, `c` char(10) NOT NULL,
`d` varchar(20) DEFAULT NULL, `d` varchar(20) DEFAULT NULL,
PRIMARY KEY (`a`),
KEY `d2` (`d`), KEY `d2` (`d`),
KEY `b` (`b`) KEY `b` (`b`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ) ENGINE=InnoDB DEFAULT CHARSET=latin1
...@@ -55,7 +52,42 @@ Table Create Table ...@@ -55,7 +52,42 @@ Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL, `a` int(11) NOT NULL,
`b` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL,
`c` char(10) DEFAULT NULL, `c` char(10) NOT NULL,
`d` varchar(20) DEFAULT NULL,
UNIQUE KEY `c` (`c`),
KEY `d2` (`d`),
KEY `b` (`b`),
KEY `d` (`d`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
explain select * from t1 order by c;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL c 10 NULL 4
drop index c on t1;
ERROR 42000: This table type requires a primary key
alter table t1 add primary key (a), drop index c;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL,
`b` int(11) DEFAULT NULL,
`c` char(10) NOT NULL,
`d` varchar(20) DEFAULT NULL,
PRIMARY KEY (`a`),
KEY `d2` (`d`),
KEY `b` (`b`),
KEY `d` (`d`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
alter table t1 add primary key (c);
ERROR 42000: Multiple primary key defined
alter table t1 drop primary key, add primary key (b);
ERROR 23000: Duplicate entry '4' for key 'PRIMARY'
create unique index c on t1 (c);
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL,
`b` int(11) DEFAULT NULL,
`c` char(10) NOT NULL,
`d` varchar(20) DEFAULT NULL, `d` varchar(20) DEFAULT NULL,
PRIMARY KEY (`a`), PRIMARY KEY (`a`),
UNIQUE KEY `c` (`c`), UNIQUE KEY `c` (`c`),
...@@ -65,7 +97,7 @@ t1 CREATE TABLE `t1` ( ...@@ -65,7 +97,7 @@ t1 CREATE TABLE `t1` (
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ) ENGINE=InnoDB DEFAULT CHARSET=latin1
explain select * from t1 order by c; explain select * from t1 order by c;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL c 11 NULL 4 1 SIMPLE t1 index NULL c 10 NULL 4
select * from t1 order by c; select * from t1 order by c;
a b c d a b c d
3 4 ad ad 3 4 ad ad
...@@ -78,7 +110,7 @@ Table Create Table ...@@ -78,7 +110,7 @@ Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL, `a` int(11) NOT NULL,
`b` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL,
`c` char(10) DEFAULT NULL, `c` char(10) NOT NULL,
`d` varchar(20) DEFAULT NULL, `d` varchar(20) DEFAULT NULL,
PRIMARY KEY (`a`), PRIMARY KEY (`a`),
UNIQUE KEY `c` (`c`), UNIQUE KEY `c` (`c`),
...@@ -120,7 +152,7 @@ id select_type table type possible_keys key key_len ref rows Extra ...@@ -120,7 +152,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL b 5 NULL 5 1 SIMPLE t1 index NULL b 5 NULL 5
explain select * from t1 order by c; explain select * from t1 order by c;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL c 11 NULL 5 1 SIMPLE t1 index NULL c 10 NULL 5
explain select * from t1 order by d; explain select * from t1 order by d;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL d2 23 NULL 5 1 SIMPLE t1 index NULL d2 23 NULL 5
...@@ -129,7 +161,7 @@ Table Create Table ...@@ -129,7 +161,7 @@ Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL, `a` int(11) NOT NULL,
`b` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL,
`c` char(10) DEFAULT NULL, `c` char(10) NOT NULL,
`d` varchar(20) DEFAULT NULL, `d` varchar(20) DEFAULT NULL,
PRIMARY KEY (`a`), PRIMARY KEY (`a`),
UNIQUE KEY `c` (`c`), UNIQUE KEY `c` (`c`),
...@@ -481,7 +513,7 @@ engine = innodb default charset=utf8; ...@@ -481,7 +513,7 @@ engine = innodb default charset=utf8;
insert into t1 values (1,1,'ab','ab'),(2,2,'ac','ac'),(3,2,'ad','ad'),(4,4,'afe','afe'); insert into t1 values (1,1,'ab','ab'),(2,2,'ac','ac'),(3,2,'ad','ad'),(4,4,'afe','afe');
commit; commit;
alter table t1 add unique index (b); alter table t1 add unique index (b);
ERROR 23000: Duplicate entry '' for key 'b' ERROR 23000: Duplicate entry '2' for key 'b'
insert into t1 values(8,9,'fff','fff'); insert into t1 values(8,9,'fff','fff');
select * from t1; select * from t1;
a b c d a b c d
...@@ -650,7 +682,7 @@ engine = innodb default charset=ucs2; ...@@ -650,7 +682,7 @@ engine = innodb default charset=ucs2;
insert into t1 values (1,1,'ab','ab'),(2,2,'ac','ac'),(3,2,'ad','ad'),(4,4,'afe','afe'); insert into t1 values (1,1,'ab','ab'),(2,2,'ac','ac'),(3,2,'ad','ad'),(4,4,'afe','afe');
commit; commit;
alter table t1 add unique index (b); alter table t1 add unique index (b);
ERROR 23000: Duplicate entry '' for key 'b' ERROR 23000: Duplicate entry '2' for key 'b'
show create table t1; show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
...@@ -771,11 +803,11 @@ drop table t1; ...@@ -771,11 +803,11 @@ drop table t1;
create table t1(a int not null, b int) engine = innodb; create table t1(a int not null, b int) engine = innodb;
insert into t1 values (1,1),(1,1),(1,1),(1,1); insert into t1 values (1,1),(1,1),(1,1),(1,1);
alter table t1 add unique index (a); alter table t1 add unique index (a);
ERROR 23000: Duplicate entry '0' for key 'a' ERROR 23000: Duplicate entry '1' for key 'a'
alter table t1 add unique index (b); alter table t1 add unique index (b);
ERROR 23000: Duplicate entry '0' for key 'b' ERROR 23000: Duplicate entry '1' for key 'b'
alter table t1 add unique index (a), add unique index(b); alter table t1 add unique index (a), add unique index(b);
ERROR 23000: Duplicate entry '0' for key 'a' ERROR 23000: Duplicate entry '1' for key 'a'
show create table t1; show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
...@@ -808,9 +840,9 @@ drop table t1; ...@@ -808,9 +840,9 @@ drop table t1;
create table t1(a int not null, b int, c char(10), d varchar(20), primary key (a)) engine = innodb; create table t1(a int not null, b int, c char(10), d varchar(20), primary key (a)) engine = innodb;
insert into t1 values (1,1,'ab','ab'),(2,2,'ac','ac'),(3,3,'ac','ac'),(4,4,'afe','afe'); insert into t1 values (1,1,'ab','ab'),(2,2,'ac','ac'),(3,3,'ac','ac'),(4,4,'afe','afe');
alter table t1 add unique index (b), add unique index (c), add unique index (d); alter table t1 add unique index (b), add unique index (c), add unique index (d);
ERROR 23000: Duplicate entry '' for key 'c' ERROR 23000: Duplicate entry 'ac' for key 'c'
alter table t1 add unique index (b), add index (d), add unique index (c); alter table t1 add unique index (b), add index (d), add unique index (c);
ERROR 23000: Duplicate entry '' for key 'c' ERROR 23000: Duplicate entry 'ac' for key 'c'
show create table t1; show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
......
-- source include/have_innodb.inc -- source include/have_innodb.inc
create table t1(a int not null, b int, c char(10), d varchar(20), primary key (a)) engine = innodb; create table t1(a int not null, b int, c char(10) not null, d varchar(20)) engine = innodb;
insert into t1 values (5,5,'oo','oo'),(4,4,'tr','tr'),(3,4,'ad','ad'),(2,3,'ak','ak'); insert into t1 values (5,5,'oo','oo'),(4,4,'tr','tr'),(3,4,'ad','ad'),(2,3,'ak','ak');
commit; commit;
--error ER_DUP_KEYNAME --error ER_DUP_KEYNAME
...@@ -19,6 +19,17 @@ show create table t1; ...@@ -19,6 +19,17 @@ show create table t1;
alter table t1 add unique index (c), add index (d); alter table t1 add unique index (c), add index (d);
show create table t1; show create table t1;
explain select * from t1 order by c; explain select * from t1 order by c;
--error ER_REQUIRES_PRIMARY_KEY
drop index c on t1;
alter table t1 add primary key (a), drop index c;
show create table t1;
--error ER_MULTIPLE_PRI_KEY
alter table t1 add primary key (c);
--error ER_DUP_ENTRY
alter table t1 drop primary key, add primary key (b);
create unique index c on t1 (c);
show create table t1;
explain select * from t1 order by c;
select * from t1 order by c; select * from t1 order by c;
alter table t1 drop index b, add index (b); alter table t1 drop index b, add index (b);
show create table t1; show create table t1;
...@@ -132,7 +143,6 @@ create table t1(a int not null, b int, c char(10), d varchar(20), primary key (a ...@@ -132,7 +143,6 @@ create table t1(a int not null, b int, c char(10), d varchar(20), primary key (a
engine = innodb default charset=utf8; engine = innodb default charset=utf8;
insert into t1 values (1,1,'ab','ab'),(2,2,'ac','ac'),(3,2,'ad','ad'),(4,4,'afe','afe'); insert into t1 values (1,1,'ab','ab'),(2,2,'ac','ac'),(3,2,'ad','ad'),(4,4,'afe','afe');
commit; commit;
--replace_regex /Duplicate entry '[0-9]*'/Duplicate entry ''/
--error ER_DUP_ENTRY --error ER_DUP_ENTRY
alter table t1 add unique index (b); alter table t1 add unique index (b);
insert into t1 values(8,9,'fff','fff'); insert into t1 values(8,9,'fff','fff');
...@@ -171,7 +181,6 @@ create table t1(a int not null, b int, c char(10), d varchar(20), primary key (a ...@@ -171,7 +181,6 @@ create table t1(a int not null, b int, c char(10), d varchar(20), primary key (a
engine = innodb default charset=ucs2; engine = innodb default charset=ucs2;
insert into t1 values (1,1,'ab','ab'),(2,2,'ac','ac'),(3,2,'ad','ad'),(4,4,'afe','afe'); insert into t1 values (1,1,'ab','ab'),(2,2,'ac','ac'),(3,2,'ad','ad'),(4,4,'afe','afe');
commit; commit;
--replace_regex /Duplicate entry '[0-9]*'/Duplicate entry ''/
--error ER_DUP_ENTRY --error ER_DUP_ENTRY
alter table t1 add unique index (b); alter table t1 add unique index (b);
show create table t1; show create table t1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment