summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Petrunia <psergey@askmonty.org>2016-07-11 22:22:32 +0300
committerSergei Petrunia <psergey@askmonty.org>2016-07-12 21:49:18 +0300
commit8a8ba1949bf4bdc1dd6504d88d20cfa3ef2c0794 (patch)
tree2281c19814c67e4f0b0217f1279cfffb2e89db6a
parent0bb5d955423c2a7b29eab02e7bf6194ae003ae75 (diff)
downloadmariadb-git-8a8ba1949bf4bdc1dd6504d88d20cfa3ef2c0794.tar.gz
MDEV-10360: Extended keys: index properties depend on index order
TABLE_SHARE::init_from_binary_frm_image has a rule: if an index has a partially-covered column (like in "KEY(col(N))" ), then dont provide "Extended Keys" feature for this index. The problem was that due to coding error Extended Keys feature was disabled for *ALL* subsequent indexes. Fixed the error.
-rw-r--r--mysql-test/r/innodb_ext_key.result45
-rw-r--r--mysql-test/t/innodb_ext_key.test53
-rw-r--r--sql/table.cc8
3 files changed, 103 insertions, 3 deletions
diff --git a/mysql-test/r/innodb_ext_key.result b/mysql-test/r/innodb_ext_key.result
index bd4bdb28fff..c0b91c88d8a 100644
--- a/mysql-test/r/innodb_ext_key.result
+++ b/mysql-test/r/innodb_ext_key.result
@@ -1064,5 +1064,50 @@ explain select * from t1 where col1='1234567890-a';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL idx1 NULL NULL NULL # Using where
drop table t0,t1;
+#
+# MDEV-10360: Extended keys: index properties depend on index order
+#
+create table t0 (a int);
+insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t1 (
+index_id bigint(20) unsigned NOT NULL,
+index_class varchar(265) COLLATE latin1_general_ci DEFAULT NULL ,
+index_object_id int(10) unsigned NOT NULL DEFAULT '0' ,
+index_date_updated int(10) unsigned DEFAULT NULL ,
+PRIMARY KEY (index_id),
+KEY object (index_class(181),index_object_id),
+KEY index_date_updated (index_date_updated)
+) engine=innodb;
+create table t2 (
+index_id bigint(20) unsigned NOT NULL,
+index_class varchar(265) COLLATE latin1_general_ci DEFAULT NULL ,
+index_object_id int(10) unsigned NOT NULL DEFAULT '0' ,
+index_date_updated int(10) unsigned DEFAULT NULL ,
+PRIMARY KEY (index_id),
+KEY index_date_updated (index_date_updated),
+KEY object (index_class(181),index_object_id)
+) engine=innodb;
+insert into t1 select
+@a:=A.a + 10*B.a + 100*C.a,
+concat('val-', @a),
+123456,
+A.a + 10*B.a
+from
+t0 A, t0 B, t0 C;
+insert into t2 select * from t1;
+# This must have the same query plan as the query below it:
+# type=range, key=index_date_updated, key_len=13
+explain
+select * from t1 force index(index_date_updated)
+where index_date_updated= 10 and index_id < 800;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range index_date_updated index_date_updated 13 NULL # Using index condition
+# This used to work from the start:
+explain
+select * from t2 force index(index_date_updated)
+where index_date_updated= 10 and index_id < 800;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range index_date_updated index_date_updated 13 NULL # Using index condition
+drop table t0,t1,t2;
set optimizer_switch=@save_ext_key_optimizer_switch;
SET SESSION STORAGE_ENGINE=DEFAULT;
diff --git a/mysql-test/t/innodb_ext_key.test b/mysql-test/t/innodb_ext_key.test
index ec774b638e8..ebea442d8ca 100644
--- a/mysql-test/t/innodb_ext_key.test
+++ b/mysql-test/t/innodb_ext_key.test
@@ -721,5 +721,58 @@ explain select * from t1 where col1='1234567890-a';
drop table t0,t1;
+--echo #
+--echo # MDEV-10360: Extended keys: index properties depend on index order
+--echo #
+create table t0 (a int);
+insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+
+create table t1 (
+ index_id bigint(20) unsigned NOT NULL,
+ index_class varchar(265) COLLATE latin1_general_ci DEFAULT NULL ,
+ index_object_id int(10) unsigned NOT NULL DEFAULT '0' ,
+ index_date_updated int(10) unsigned DEFAULT NULL ,
+
+ PRIMARY KEY (index_id),
+ KEY object (index_class(181),index_object_id),
+ KEY index_date_updated (index_date_updated)
+) engine=innodb;
+
+create table t2 (
+ index_id bigint(20) unsigned NOT NULL,
+ index_class varchar(265) COLLATE latin1_general_ci DEFAULT NULL ,
+ index_object_id int(10) unsigned NOT NULL DEFAULT '0' ,
+ index_date_updated int(10) unsigned DEFAULT NULL ,
+
+ PRIMARY KEY (index_id),
+ KEY index_date_updated (index_date_updated),
+ KEY object (index_class(181),index_object_id)
+) engine=innodb;
+
+insert into t1 select
+ @a:=A.a + 10*B.a + 100*C.a,
+ concat('val-', @a),
+ 123456,
+ A.a + 10*B.a
+from
+ t0 A, t0 B, t0 C;
+
+insert into t2 select * from t1;
+
+--echo # This must have the same query plan as the query below it:
+--echo # type=range, key=index_date_updated, key_len=13
+--replace_column 9 #
+explain
+select * from t1 force index(index_date_updated)
+where index_date_updated= 10 and index_id < 800;
+
+--echo # This used to work from the start:
+--replace_column 9 #
+explain
+select * from t2 force index(index_date_updated)
+where index_date_updated= 10 and index_id < 800;
+
+drop table t0,t1,t2;
+
set optimizer_switch=@save_ext_key_optimizer_switch;
SET SESSION STORAGE_ENGINE=DEFAULT;
diff --git a/sql/table.cc b/sql/table.cc
index f7dddd92553..85ffd560992 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -1804,6 +1804,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
{
KEY_PART_INFO *new_key_part= (keyinfo-1)->key_part +
(keyinfo-1)->ext_key_parts;
+ uint add_keyparts_for_this_key= add_first_key_parts;
/*
Do not extend the key that contains a component
@@ -1815,19 +1816,20 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
if (share->field[fieldnr-1]->key_length() !=
keyinfo->key_part[i].length)
{
- add_first_key_parts= 0;
+ add_keyparts_for_this_key= 0;
break;
}
}
- if (add_first_key_parts < keyinfo->ext_key_parts-keyinfo->user_defined_key_parts)
+ if (add_keyparts_for_this_key < (keyinfo->ext_key_parts -
+ keyinfo->user_defined_key_parts))
{
share->ext_key_parts-= keyinfo->ext_key_parts;
key_part_map ext_key_part_map= keyinfo->ext_key_part_map;
keyinfo->ext_key_parts= keyinfo->user_defined_key_parts;
keyinfo->ext_key_flags= keyinfo->flags;
keyinfo->ext_key_part_map= 0;
- for (i= 0; i < add_first_key_parts; i++)
+ for (i= 0; i < add_keyparts_for_this_key; i++)
{
if (ext_key_part_map & 1<<i)
{