Commit 201fb06d authored by Sergey Petrunya's avatar Sergey Petrunya

Merge in fix for BUG#727667

parents ec239491 0fe8c972
...@@ -170,7 +170,7 @@ insert into t1 select i*2 from t1; ...@@ -170,7 +170,7 @@ insert into t1 select i*2 from t1;
insert into t1 values(null); insert into t1 values(null);
explain select * from t1 where i=2 or i is null; explain select * from t1 where i=2 or i is null;
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 ref_or_null i i 5 const 9 Using index 1 SIMPLE t1 ref_or_null i i 5 const 9 Using where; Using index
select count(*) from t1 where i=2 or i is null; select count(*) from t1 where i=2 or i is null;
count(*) count(*)
10 10
......
...@@ -21,10 +21,10 @@ id select_type table type possible_keys key key_len ref rows Extra ...@@ -21,10 +21,10 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range a,b a 9 NULL 3 Using where; Using index 1 SIMPLE t1 range a,b a 9 NULL 3 Using where; Using index
explain select * from t1 where (a is null or a = 7) and b=7; explain select * from t1 where (a is null or a = 7) and b=7;
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 ref_or_null a,b a 9 const,const 2 Using index 1 SIMPLE t1 ref_or_null a,b a 9 const,const 2 Using where; Using index
explain select * from t1 where (a is null or a = 7) and b=7 order by a; explain select * from t1 where (a is null or a = 7) and b=7 order by a;
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 ref_or_null a,b a 9 const,const 2 Using index; Using filesort 1 SIMPLE t1 ref_or_null a,b a 9 const,const 2 Using where; Using index; Using filesort
explain select * from t1 where (a is null and b>a) or a is null and b=7 limit 2; explain select * from t1 where (a is null and b>a) or a is null and b=7 limit 2;
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 ref a,b a 5 const 3 Using where; Using index 1 SIMPLE t1 ref a,b a 5 const 3 Using where; Using index
...@@ -151,7 +151,7 @@ alter table t1 modify b int null; ...@@ -151,7 +151,7 @@ alter table t1 modify b int null;
insert into t1 values (7,null), (8,null), (8,7); insert into t1 values (7,null), (8,null), (8,7);
explain select * from t1 where a = 7 and (b=7 or b is null); explain select * from t1 where a = 7 and (b=7 or b is null);
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 ref_or_null a,b a 10 const,const 2 Using index 1 SIMPLE t1 ref_or_null a,b a 10 const,const 2 Using where; Using index
select * from t1 where a = 7 and (b=7 or b is null); select * from t1 where a = 7 and (b=7 or b is null);
a b a b
7 7 7 7
...@@ -166,7 +166,7 @@ a b ...@@ -166,7 +166,7 @@ a b
NULL 7 NULL 7
explain select * from t1 where (a = 7 or a is null) and (a = 7 or a is null); explain select * from t1 where (a = 7 or a is null) and (a = 7 or a is null);
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 ref_or_null a a 5 const 5 Using index 1 SIMPLE t1 ref_or_null a a 5 const 5 Using where; Using index
select * from t1 where (a = 7 or a is null) and (a = 7 or a is null); select * from t1 where (a = 7 or a is null) and (a = 7 or a is null);
a b a b
7 NULL 7 NULL
...@@ -192,7 +192,7 @@ a a b ...@@ -192,7 +192,7 @@ a a b
explain select * from t2,t1 where t1.a=t2.a and (b= 7 or b is null); explain select * from t2,t1 where t1.a=t2.a and (b= 7 or b is null);
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 t2 ALL NULL NULL NULL NULL 2 Using where 1 SIMPLE t2 ALL NULL NULL NULL NULL 2 Using where
1 SIMPLE t1 ref_or_null a a 10 test.t2.a,const 4 Using index 1 SIMPLE t1 ref_or_null a a 10 test.t2.a,const 4 Using where; Using index
select * from t2,t1 where t1.a=t2.a and (b= 7 or b is null); select * from t2,t1 where t1.a=t2.a and (b= 7 or b is null);
a a b a a b
7 7 7 7 7 7
...@@ -202,7 +202,7 @@ a a b ...@@ -202,7 +202,7 @@ a a b
explain select * from t2,t1 where (t1.a=t2.a or t1.a is null) and b= 7; explain select * from t2,t1 where (t1.a=t2.a or t1.a is null) and b= 7;
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 t2 ALL NULL NULL NULL NULL 2 1 SIMPLE t2 ALL NULL NULL NULL NULL 2
1 SIMPLE t1 ref_or_null a a 10 test.t2.a,const 4 Using index 1 SIMPLE t1 ref_or_null a a 10 test.t2.a,const 4 Using where; Using index
select * from t2,t1 where (t1.a=t2.a or t1.a is null) and b= 7; select * from t2,t1 where (t1.a=t2.a or t1.a is null) and b= 7;
a a b a a b
7 7 7 7 7 7
...@@ -226,7 +226,7 @@ delete from t1 where a=8; ...@@ -226,7 +226,7 @@ delete from t1 where a=8;
explain select * from t2,t1 where t1.a=t2.a or t1.a is null; explain select * from t2,t1 where t1.a=t2.a or t1.a is null;
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 t2 ALL NULL NULL NULL NULL 4 1 SIMPLE t2 ALL NULL NULL NULL NULL 4
1 SIMPLE t1 ref_or_null a a 5 test.t2.a 4 Using index 1 SIMPLE t1 ref_or_null a a 5 test.t2.a 4 Using where; Using index
explain select * from t2,t1 where t1.a<=>t2.a or (t1.a is null and t1.b <> 9); explain select * from t2,t1 where t1.a<=>t2.a or (t1.a is null and t1.b <> 9);
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 t2 ALL NULL NULL NULL NULL 4 1 SIMPLE t2 ALL NULL NULL NULL NULL 4
...@@ -447,3 +447,15 @@ a b a b ...@@ -447,3 +447,15 @@ a b a b
3 12 0 12 3 12 0 12
drop table t1, t2; drop table t1, t2;
End of 5.0 tests End of 5.0 tests
#
# BUG#727667 Wrong result with OR + NOT NULL in maria-5.3
#
CREATE TABLE t1 (
f3 int(11),
f10 varchar(1),
KEY (f3)
);
INSERT INTO t1 VALUES ('9','k'),(NULL,'r');
SELECT * FROM t1 WHERE (f3 = 83) OR (f10 = 'z' AND f3 IS NULL);
f3 f10
DROP TABLE t1;
...@@ -643,7 +643,7 @@ create table t1(a int, b int, index(b)); ...@@ -643,7 +643,7 @@ create table t1(a int, b int, index(b));
insert into t1 values (2, 1), (1, 1), (4, NULL), (3, NULL), (6, 2), (5, 2); insert into t1 values (2, 1), (1, 1), (4, NULL), (3, NULL), (6, 2), (5, 2);
explain select * from t1 where b=1 or b is null order by a; explain select * from t1 where b=1 or b is null order by a;
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 ref_or_null b b 5 const 3 Using filesort 1 SIMPLE t1 ref_or_null b b 5 const 3 Using index condition; Using filesort
select * from t1 where b=1 or b is null order by a; select * from t1 where b=1 or b is null order by a;
a b a b
1 1 1 1
...@@ -652,7 +652,7 @@ a b ...@@ -652,7 +652,7 @@ a b
4 NULL 4 NULL
explain select * from t1 where b=2 or b is null order by a; explain select * from t1 where b=2 or b is null order by a;
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 ref_or_null b b 5 const 4 Using filesort 1 SIMPLE t1 ref_or_null b b 5 const 4 Using index condition; Using filesort
select * from t1 where b=2 or b is null order by a; select * from t1 where b=2 or b is null order by a;
a b a b
3 NULL 3 NULL
......
...@@ -906,7 +906,7 @@ a t1.a in (select t2.a from t2,t3 where t3.a=t2.a) ...@@ -906,7 +906,7 @@ a t1.a in (select t2.a from t2,t3 where t3.a=t2.a)
explain extended SELECT t1.a, t1.a in (select t2.a from t2,t3 where t3.a=t2.a) FROM t1; explain extended SELECT t1.a, t1.a in (select t2.a from t2,t3 where t3.a=t2.a) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL PRIMARY 4 NULL 4 100.00 Using index 1 PRIMARY t1 index NULL PRIMARY 4 NULL 4 100.00 Using index
2 DEPENDENT SUBQUERY t2 ref_or_null a a 5 func 2 100.00 Using index 2 DEPENDENT SUBQUERY t2 ref_or_null a a 5 func 2 100.00 Using where; Using index
2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join) 2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
Warnings: Warnings:
Note 1003 select `test`.`t1`.`a` AS `a`,<expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,<exists>(select 1 from `test`.`t2` join `test`.`t3` where ((`test`.`t3`.`a` = `test`.`t2`.`a`) and ((<cache>(`test`.`t1`.`a`) = `test`.`t2`.`a`) or isnull(`test`.`t2`.`a`))) having <is_not_null_test>(`test`.`t2`.`a`)))) AS `t1.a in (select t2.a from t2,t3 where t3.a=t2.a)` from `test`.`t1` Note 1003 select `test`.`t1`.`a` AS `a`,<expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,<exists>(select 1 from `test`.`t2` join `test`.`t3` where ((`test`.`t3`.`a` = `test`.`t2`.`a`) and ((<cache>(`test`.`t1`.`a`) = `test`.`t2`.`a`) or isnull(`test`.`t2`.`a`))) having <is_not_null_test>(`test`.`t2`.`a`)))) AS `t1.a in (select t2.a from t2,t3 where t3.a=t2.a)` from `test`.`t1`
......
...@@ -910,7 +910,7 @@ a t1.a in (select t2.a from t2,t3 where t3.a=t2.a) ...@@ -910,7 +910,7 @@ a t1.a in (select t2.a from t2,t3 where t3.a=t2.a)
explain extended SELECT t1.a, t1.a in (select t2.a from t2,t3 where t3.a=t2.a) FROM t1; explain extended SELECT t1.a, t1.a in (select t2.a from t2,t3 where t3.a=t2.a) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL PRIMARY 4 NULL 4 100.00 Using index 1 PRIMARY t1 index NULL PRIMARY 4 NULL 4 100.00 Using index
2 DEPENDENT SUBQUERY t2 ref_or_null a a 5 func 2 100.00 Using index 2 DEPENDENT SUBQUERY t2 ref_or_null a a 5 func 2 100.00 Using where; Using index
2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join) 2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
Warnings: Warnings:
Note 1003 select `test`.`t1`.`a` AS `a`,<expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,<exists>(select 1 from `test`.`t2` join `test`.`t3` where ((`test`.`t3`.`a` = `test`.`t2`.`a`) and ((<cache>(`test`.`t1`.`a`) = `test`.`t2`.`a`) or isnull(`test`.`t2`.`a`))) having <is_not_null_test>(`test`.`t2`.`a`)))) AS `t1.a in (select t2.a from t2,t3 where t3.a=t2.a)` from `test`.`t1` Note 1003 select `test`.`t1`.`a` AS `a`,<expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,<exists>(select 1 from `test`.`t2` join `test`.`t3` where ((`test`.`t3`.`a` = `test`.`t2`.`a`) and ((<cache>(`test`.`t1`.`a`) = `test`.`t2`.`a`) or isnull(`test`.`t2`.`a`))) having <is_not_null_test>(`test`.`t2`.`a`)))) AS `t1.a in (select t2.a from t2,t3 where t3.a=t2.a)` from `test`.`t1`
......
...@@ -907,7 +907,7 @@ a t1.a in (select t2.a from t2,t3 where t3.a=t2.a) ...@@ -907,7 +907,7 @@ a t1.a in (select t2.a from t2,t3 where t3.a=t2.a)
explain extended SELECT t1.a, t1.a in (select t2.a from t2,t3 where t3.a=t2.a) FROM t1; explain extended SELECT t1.a, t1.a in (select t2.a from t2,t3 where t3.a=t2.a) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL PRIMARY 4 NULL 4 100.00 Using index 1 PRIMARY t1 index NULL PRIMARY 4 NULL 4 100.00 Using index
2 DEPENDENT SUBQUERY t2 ref_or_null a a 5 func 2 100.00 Using index 2 DEPENDENT SUBQUERY t2 ref_or_null a a 5 func 2 100.00 Using where; Using index
2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join) 2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
Warnings: Warnings:
Note 1003 select `test`.`t1`.`a` AS `a`,<expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,<exists>(select 1 from `test`.`t2` join `test`.`t3` where ((`test`.`t3`.`a` = `test`.`t2`.`a`) and ((<cache>(`test`.`t1`.`a`) = `test`.`t2`.`a`) or isnull(`test`.`t2`.`a`))) having <is_not_null_test>(`test`.`t2`.`a`)))) AS `t1.a in (select t2.a from t2,t3 where t3.a=t2.a)` from `test`.`t1` Note 1003 select `test`.`t1`.`a` AS `a`,<expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,<exists>(select 1 from `test`.`t2` join `test`.`t3` where ((`test`.`t3`.`a` = `test`.`t2`.`a`) and ((<cache>(`test`.`t1`.`a`) = `test`.`t2`.`a`) or isnull(`test`.`t2`.`a`))) having <is_not_null_test>(`test`.`t2`.`a`)))) AS `t1.a in (select t2.a from t2,t3 where t3.a=t2.a)` from `test`.`t1`
......
...@@ -907,7 +907,7 @@ a t1.a in (select t2.a from t2,t3 where t3.a=t2.a) ...@@ -907,7 +907,7 @@ a t1.a in (select t2.a from t2,t3 where t3.a=t2.a)
explain extended SELECT t1.a, t1.a in (select t2.a from t2,t3 where t3.a=t2.a) FROM t1; explain extended SELECT t1.a, t1.a in (select t2.a from t2,t3 where t3.a=t2.a) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL PRIMARY 4 NULL 4 100.00 Using index 1 PRIMARY t1 index NULL PRIMARY 4 NULL 4 100.00 Using index
2 DEPENDENT SUBQUERY t2 ref_or_null a a 5 func 2 100.00 Using index 2 DEPENDENT SUBQUERY t2 ref_or_null a a 5 func 2 100.00 Using where; Using index
2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join) 2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
Warnings: Warnings:
Note 1003 select `test`.`t1`.`a` AS `a`,<expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,<exists>(select 1 from `test`.`t2` join `test`.`t3` where ((`test`.`t3`.`a` = `test`.`t2`.`a`) and ((<cache>(`test`.`t1`.`a`) = `test`.`t2`.`a`) or isnull(`test`.`t2`.`a`))) having <is_not_null_test>(`test`.`t2`.`a`)))) AS `t1.a in (select t2.a from t2,t3 where t3.a=t2.a)` from `test`.`t1` Note 1003 select `test`.`t1`.`a` AS `a`,<expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,<exists>(select 1 from `test`.`t2` join `test`.`t3` where ((`test`.`t3`.`a` = `test`.`t2`.`a`) and ((<cache>(`test`.`t1`.`a`) = `test`.`t2`.`a`) or isnull(`test`.`t2`.`a`))) having <is_not_null_test>(`test`.`t2`.`a`)))) AS `t1.a in (select t2.a from t2,t3 where t3.a=t2.a)` from `test`.`t1`
......
...@@ -263,3 +263,16 @@ SELECT * FROM t2 inner join t1 WHERE ( t1.a = 0 OR t1.a IS NULL) AND t2.a = 3 AN ...@@ -263,3 +263,16 @@ SELECT * FROM t2 inner join t1 WHERE ( t1.a = 0 OR t1.a IS NULL) AND t2.a = 3 AN
drop table t1, t2; drop table t1, t2;
-- echo End of 5.0 tests -- echo End of 5.0 tests
--echo #
--echo # BUG#727667 Wrong result with OR + NOT NULL in maria-5.3
--echo #
CREATE TABLE t1 (
f3 int(11),
f10 varchar(1),
KEY (f3)
);
INSERT INTO t1 VALUES ('9','k'),(NULL,'r');
SELECT * FROM t1 WHERE (f3 = 83) OR (f10 = 'z' AND f3 IS NULL);
DROP TABLE t1;
...@@ -6611,10 +6611,12 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, ...@@ -6611,10 +6611,12 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j,
j->ref.has_record= FALSE; j->ref.has_record= FALSE;
j->ref.null_rejecting= 0; j->ref.null_rejecting= 0;
j->ref.disable_cache= FALSE; j->ref.disable_cache= FALSE;
j->ref.null_ref_part= NO_REF_PART;
keyuse=org_keyuse; keyuse=org_keyuse;
store_key **ref_key= j->ref.key_copy; store_key **ref_key= j->ref.key_copy;
uchar *key_buff=j->ref.key_buff, *null_ref_key= 0; uchar *key_buff=j->ref.key_buff, *null_ref_key= 0;
uint null_ref_part= NO_REF_PART;
bool keyuse_uses_no_tables= TRUE; bool keyuse_uses_no_tables= TRUE;
if (ftkey) if (ftkey)
{ {
...@@ -6668,7 +6670,10 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, ...@@ -6668,7 +6670,10 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j,
instead of JT_REF_OR_NULL in case if field can't be null instead of JT_REF_OR_NULL in case if field can't be null
*/ */
if ((keyuse->optimize & KEY_OPTIMIZE_REF_OR_NULL) && maybe_null) if ((keyuse->optimize & KEY_OPTIMIZE_REF_OR_NULL) && maybe_null)
{
null_ref_key= key_buff; null_ref_key= key_buff;
null_ref_part= i;
}
key_buff+= keyinfo->key_part[i].store_length; key_buff+= keyinfo->key_part[i].store_length;
} }
} /* not ftkey */ } /* not ftkey */
...@@ -6683,6 +6688,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, ...@@ -6683,6 +6688,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j,
/* 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;
} }
else if (keyuse_uses_no_tables) else if (keyuse_uses_no_tables)
{ {
...@@ -15356,8 +15362,12 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), ...@@ -15356,8 +15362,12 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
*****************************************************************************/ *****************************************************************************/
/** /**
Check if "left_item=right_item" equality is guaranteed to be true by use of
[eq]ref access on left_item->field->table.
@return @return
1 if right_item is used removable reference key on left_item TRUE if right_item is used removable reference key on left_item
FALSE otherwise
*/ */
bool test_if_ref(Item *root_cond, Item_field *left_item,Item *right_item) bool test_if_ref(Item *root_cond, Item_field *left_item,Item *right_item)
...@@ -15370,7 +15380,11 @@ bool test_if_ref(Item *root_cond, Item_field *left_item,Item *right_item) ...@@ -15370,7 +15380,11 @@ bool test_if_ref(Item *root_cond, Item_field *left_item,Item *right_item)
(!join_tab->first_inner || (!join_tab->first_inner ||
*join_tab->first_inner->on_expr_ref == root_cond)) *join_tab->first_inner->on_expr_ref == root_cond))
{ {
// Cond guards /*
If ref access uses "Full scan on NULL key" (i.e. it actually alternates
between ref access and full table scan), then no equality can be
guaranteed to be true.
*/
for (uint i = 0; i < join_tab->ref.key_parts; i++) for (uint i = 0; i < join_tab->ref.key_parts; i++)
{ {
if (join_tab->ref.cond_guards[i]) if (join_tab->ref.cond_guards[i])
...@@ -15378,7 +15392,7 @@ bool test_if_ref(Item *root_cond, Item_field *left_item,Item *right_item) ...@@ -15378,7 +15392,7 @@ bool test_if_ref(Item *root_cond, Item_field *left_item,Item *right_item)
return FALSE; return FALSE;
} }
} }
//
Item *ref_item=part_of_refkey(field->table,field); Item *ref_item=part_of_refkey(field->table,field);
if (ref_item && ref_item->eq(right_item,1)) if (ref_item && ref_item->eq(right_item,1))
{ {
...@@ -15680,6 +15694,29 @@ make_cond_after_sjm(Item *root_cond, Item *cond, table_map tables, ...@@ -15680,6 +15694,29 @@ make_cond_after_sjm(Item *root_cond, Item *cond, table_map tables,
} }
/*
@brief
Check if
- @table uses "ref"-like access
- it is based on "@field=certain_item" equality
- the equality will be true for any record returned by the access method
and return the certain_item if yes.
@detail
Equality won't necessarily hold if:
- the used index covers only part of the @field.
Suppose, we have a CHAR(5) field and INDEX(field(3)). if you make a lookup
for 'abc', you will get both record with 'abc' and with 'abcde'.
- The type of access is actually ref_or_null, and so @field can be either
a value or NULL.
@return
Item that the field will be equal to
NULL if no such item
*/
static Item * static Item *
part_of_refkey(TABLE *table,Field *field) part_of_refkey(TABLE *table,Field *field)
{ {
...@@ -15688,17 +15725,30 @@ part_of_refkey(TABLE *table,Field *field) ...@@ -15688,17 +15725,30 @@ part_of_refkey(TABLE *table,Field *field)
return (Item*) 0; // field from outer non-select (UPDATE,...) return (Item*) 0; // field from outer non-select (UPDATE,...)
uint ref_parts= join_tab->ref.key_parts; uint ref_parts= join_tab->ref.key_parts;
if (ref_parts) if (ref_parts) /* if it's ref/eq_ref/ref_or_null */
{ {
uint key= join_tab->ref.key; uint key= join_tab->ref.key;
KEY *key_info= join_tab->get_keyinfo_by_key_no(key); KEY *key_info= join_tab->get_keyinfo_by_key_no(key);
KEY_PART_INFO *key_part= key_info->key_part; KEY_PART_INFO *key_part= key_info->key_part;
for (uint part=0 ; part < ref_parts ; part++,key_part++) for (uint part=0 ; part < ref_parts ; part++,key_part++)
if (field->eq(key_part->field) && {
!(key_part->key_part_flag & (HA_PART_KEY_SEG | HA_NULL_PART))) if (field->eq(key_part->field))
return join_tab->ref.items[part]; {
/*
Found the field in the key. Check that
1. ref_or_null doesn't alternate this component between a value and
a NULL
2. index fully covers the key
*/
if (part != join_tab->ref.null_ref_part && // (1)
!(key_part->key_part_flag & HA_PART_KEY_SEG)) // (2)
{
return join_tab->ref.items[part];
}
break;
}
}
} }
return (Item*) 0; return (Item*) 0;
} }
......
...@@ -79,6 +79,8 @@ typedef struct keyuse_t { ...@@ -79,6 +79,8 @@ typedef struct keyuse_t {
class store_key; class store_key;
const int NO_REF_PART= uint(-1);
typedef struct st_table_ref typedef struct st_table_ref
{ {
bool key_err; bool key_err;
...@@ -109,8 +111,16 @@ typedef struct st_table_ref ...@@ -109,8 +111,16 @@ typedef struct st_table_ref
*/ */
key_part_map null_rejecting; key_part_map null_rejecting;
table_map depend_map; ///< Table depends on these tables. table_map depend_map; ///< Table depends on these tables.
/* null byte position in the key_buf. Used for REF_OR_NULL optimization */ /* null byte position in the key_buf. Used for REF_OR_NULL optimization */
uchar *null_ref_key; uchar *null_ref_key;
/*
ref_or_null optimization: number of key part that alternates between
the lookup value or NULL (there's only one such part).
If we're not using ref_or_null, the value is NO_REF_PART
*/
uint null_ref_part;
/* /*
The number of times the record associated with this key was used The number of times the record associated with this key was used
in the join. in the join.
......
...@@ -1581,6 +1581,8 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, ...@@ -1581,6 +1581,8 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
#endif #endif
key_part->key_part_flag|= HA_PART_KEY_SEG; key_part->key_part_flag|= HA_PART_KEY_SEG;
} }
if (field->real_maybe_null())
key_part->key_part_flag|= HA_NULL_PART;
/* /*
Sometimes we can compare key parts for equality with memcmp. Sometimes we can compare key parts for equality with memcmp.
But not always. But not always.
......
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