summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Babaev <igor@askmonty.org>2012-11-11 11:47:44 -0800
committerIgor Babaev <igor@askmonty.org>2012-11-11 11:47:44 -0800
commite08f4f16303c234c82c397414c24c931b679f84a (patch)
tree8bbeaeca4d2bb24dfc13acfd32c5e56307d1c293
parent0380b0e28034c8e5778e37540478f61d3d74a0bc (diff)
downloadmariadb-git-e08f4f16303c234c82c397414c24c931b679f84a.tar.gz
Fixed bug mdev-3851.
Any ref access to a table by a key fully extended by the components of the primary key should be actually an eq_ref access.
-rw-r--r--include/my_base.h3
-rw-r--r--mysql-test/r/innodb_ext_key.result20
-rw-r--r--mysql-test/t/innodb_ext_key.test21
-rw-r--r--sql/sql_select.cc22
-rw-r--r--sql/table.cc5
5 files changed, 61 insertions, 10 deletions
diff --git a/include/my_base.h b/include/my_base.h
index 905e4535360..e072bb7e2b1 100644
--- a/include/my_base.h
+++ b/include/my_base.h
@@ -282,6 +282,9 @@ enum ha_base_keytype {
#define HA_USES_BLOCK_SIZE ((uint) 32768)
#define HA_SORT_ALLOWS_SAME 512 /* Intern bit when sorting records */
+/* This flag can be used only in KEY::ext_key_flags */
+#define HA_EXT_NOSAME 131072
+
/* These flags can be added to key-seg-flag */
#define HA_SPACE_PACK 1 /* Pack space in key-seg */
diff --git a/mysql-test/r/innodb_ext_key.result b/mysql-test/r/innodb_ext_key.result
index d2fb29a023c..0b7b042a0b2 100644
--- a/mysql-test/r/innodb_ext_key.result
+++ b/mysql-test/r/innodb_ext_key.result
@@ -613,6 +613,26 @@ Handler_read_prev 0
Handler_read_rnd 0
Handler_read_rnd_deleted 0
Handler_read_rnd_next 0
+#
+# Bug mdev-3851: ref access used instead of expected eq_ref access
+# when extended_keys=on
+#
+create table t0 (a int);
+insert into t0 values (1), (2), (3), (4), (5);
+create index i_p_size on part(p_size);
+set optimizer_switch='extended_keys=on';
+explain
+select * from t0, part ignore index (primary)
+where p_partkey=t0.a and p_size=1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 ALL NULL NULL NULL NULL 5 Using where
+1 SIMPLE part eq_ref i_p_size i_p_size 9 const,dbt3_s001.t0.a 1
+select * from t0, part ignore index (primary)
+where p_partkey=t0.a and p_size=1;
+a p_partkey p_name p_mfgr p_brand p_type p_size p_container p_retailprice p_comment
+2 2 blush rosy metallic lemon navajo Manufacturer#1 Brand#13 LARGE BRUSHED BRASS 1 LG CASE 902 final platelets hang f
+drop table t0;
+drop index i_p_size on part;
DROP DATABASE dbt3_s001;
use test;
#
diff --git a/mysql-test/t/innodb_ext_key.test b/mysql-test/t/innodb_ext_key.test
index 58d692f720d..f5b5df527a3 100644
--- a/mysql-test/t/innodb_ext_key.test
+++ b/mysql-test/t/innodb_ext_key.test
@@ -287,6 +287,27 @@ select o_orderkey, p_partkey
and o_orderkey=l_orderkey and p_partkey=l_partkey;
show status like 'handler_read%';
+--echo #
+--echo # Bug mdev-3851: ref access used instead of expected eq_ref access
+--echo # when extended_keys=on
+--echo #
+
+create table t0 (a int);
+insert into t0 values (1), (2), (3), (4), (5);
+create index i_p_size on part(p_size);
+
+set optimizer_switch='extended_keys=on';
+
+explain
+select * from t0, part ignore index (primary)
+ where p_partkey=t0.a and p_size=1;
+
+select * from t0, part ignore index (primary)
+ where p_partkey=t0.a and p_size=1;
+
+drop table t0;
+drop index i_p_size on part;
+
DROP DATABASE dbt3_s001;
use test;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index b6b1259ca49..30f84142c0c 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -5378,7 +5378,8 @@ best_access_path(JOIN *join,
!ref_or_null_part)
{ /* use eq key */
max_key_part= (uint) ~0;
- if ((key_flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME)
+ if ((key_flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME ||
+ test(key_flags & HA_EXT_NOSAME))
{
tmp = prev_record_reads(join->positions, idx, found_ref);
records=1.0;
@@ -7966,18 +7967,23 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j,
*ref_key=0; // end_marker
if (j->type == JT_FT)
DBUG_RETURN(0);
+ ulong key_flags= j->table->actual_key_flags(keyinfo);
if (j->type == JT_CONST)
j->table->const_table= 1;
- else if (((j->table->actual_key_flags(keyinfo) &
- (HA_NOSAME | HA_NULL_PART_KEY))
- != HA_NOSAME) ||
+ else if (((key_flags & (HA_NOSAME | HA_NULL_PART_KEY))!= HA_NOSAME) ||
keyparts != j->table->actual_n_key_parts(keyinfo) ||
null_ref_key)
{
- /* Must read with repeat */
- j->type= null_ref_key ? JT_REF_OR_NULL : JT_REF;
- j->ref.null_ref_key= null_ref_key;
- j->ref.null_ref_part= null_ref_part;
+ if (test(key_flags & HA_EXT_NOSAME) && keyparts == keyinfo->ext_key_parts &&
+ !null_ref_key)
+ j->type= JT_EQ_REF;
+ else
+ {
+ /* Must read with repeat */
+ j->type= null_ref_key ? JT_REF_OR_NULL : JT_REF;
+ j->ref.null_ref_key= null_ref_key;
+ j->ref.null_ref_part= null_ref_part;
+ }
}
else if (keyuse_uses_no_tables)
{
diff --git a/sql/table.cc b/sql/table.cc
index c0e27b9a962..9f94054a1e6 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -981,7 +981,6 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
keyinfo->ext_key_part_map= 0;
if (share->use_ext_keys && i)
{
- keyinfo->ext_key_flags= keyinfo->flags | HA_NOSAME;
keyinfo->ext_key_part_map= 0;
for (j= 0;
j < first_key_parts && keyinfo->ext_key_parts < MAX_REF_PARTS;
@@ -1002,7 +1001,9 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
keyinfo->ext_key_parts++;
keyinfo->ext_key_part_map|= 1 << j;
}
- }
+ }
+ if (j == first_key_parts)
+ keyinfo->ext_key_flags= keyinfo->flags | HA_NOSAME | HA_EXT_NOSAME;
}
share->ext_key_parts+= keyinfo->ext_key_parts;
}