Commit e08f4f16 authored by Igor Babaev's avatar Igor Babaev

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.
parent 0380b0e2
...@@ -282,6 +282,9 @@ enum ha_base_keytype { ...@@ -282,6 +282,9 @@ enum ha_base_keytype {
#define HA_USES_BLOCK_SIZE ((uint) 32768) #define HA_USES_BLOCK_SIZE ((uint) 32768)
#define HA_SORT_ALLOWS_SAME 512 /* Intern bit when sorting records */ #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 */ /* These flags can be added to key-seg-flag */
#define HA_SPACE_PACK 1 /* Pack space in key-seg */ #define HA_SPACE_PACK 1 /* Pack space in key-seg */
......
...@@ -613,6 +613,26 @@ Handler_read_prev 0 ...@@ -613,6 +613,26 @@ Handler_read_prev 0
Handler_read_rnd 0 Handler_read_rnd 0
Handler_read_rnd_deleted 0 Handler_read_rnd_deleted 0
Handler_read_rnd_next 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; DROP DATABASE dbt3_s001;
use test; use test;
# #
......
...@@ -287,6 +287,27 @@ select o_orderkey, p_partkey ...@@ -287,6 +287,27 @@ select o_orderkey, p_partkey
and o_orderkey=l_orderkey and p_partkey=l_partkey; and o_orderkey=l_orderkey and p_partkey=l_partkey;
show status like 'handler_read%'; 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; DROP DATABASE dbt3_s001;
use test; use test;
......
...@@ -5378,7 +5378,8 @@ best_access_path(JOIN *join, ...@@ -5378,7 +5378,8 @@ best_access_path(JOIN *join,
!ref_or_null_part) !ref_or_null_part)
{ /* use eq key */ { /* use eq key */
max_key_part= (uint) ~0; 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); tmp = prev_record_reads(join->positions, idx, found_ref);
records=1.0; records=1.0;
...@@ -7966,19 +7967,24 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, ...@@ -7966,19 +7967,24 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j,
*ref_key=0; // end_marker *ref_key=0; // end_marker
if (j->type == JT_FT) if (j->type == JT_FT)
DBUG_RETURN(0); DBUG_RETURN(0);
ulong key_flags= j->table->actual_key_flags(keyinfo);
if (j->type == JT_CONST) if (j->type == JT_CONST)
j->table->const_table= 1; j->table->const_table= 1;
else if (((j->table->actual_key_flags(keyinfo) & else if (((key_flags & (HA_NOSAME | HA_NULL_PART_KEY))!= HA_NOSAME) ||
(HA_NOSAME | HA_NULL_PART_KEY))
!= HA_NOSAME) ||
keyparts != j->table->actual_n_key_parts(keyinfo) || keyparts != j->table->actual_n_key_parts(keyinfo) ||
null_ref_key) null_ref_key)
{
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 */ /* Must read with repeat */
j->type= null_ref_key ? JT_REF_OR_NULL : JT_REF; j->type= null_ref_key ? JT_REF_OR_NULL : JT_REF;
j->ref.null_ref_key= null_ref_key; j->ref.null_ref_key= null_ref_key;
j->ref.null_ref_part= null_ref_part; j->ref.null_ref_part= null_ref_part;
} }
}
else if (keyuse_uses_no_tables) else if (keyuse_uses_no_tables)
{ {
/* /*
......
...@@ -981,7 +981,6 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, ...@@ -981,7 +981,6 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
keyinfo->ext_key_part_map= 0; keyinfo->ext_key_part_map= 0;
if (share->use_ext_keys && i) if (share->use_ext_keys && i)
{ {
keyinfo->ext_key_flags= keyinfo->flags | HA_NOSAME;
keyinfo->ext_key_part_map= 0; keyinfo->ext_key_part_map= 0;
for (j= 0; for (j= 0;
j < first_key_parts && keyinfo->ext_key_parts < MAX_REF_PARTS; j < first_key_parts && keyinfo->ext_key_parts < MAX_REF_PARTS;
...@@ -1003,6 +1002,8 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, ...@@ -1003,6 +1002,8 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
keyinfo->ext_key_part_map|= 1 << j; 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; share->ext_key_parts+= keyinfo->ext_key_parts;
} }
......
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