Commit 430157e6 authored by gkodinov/kgeorge@magare.gmz's avatar gkodinov/kgeorge@magare.gmz

Merge gkodinov@bk-internal.mysql.com:/home/bk/mysql-5.0-opt

into  magare.gmz:/home/kgeorge/mysql/autopush/B30788-5.0-opt
parents 9fed61c3 2e2ac428
...@@ -1307,7 +1307,7 @@ id select_type table type possible_keys key key_len ref rows Extra ...@@ -1307,7 +1307,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 index NULL PRIMARY 4 NULL 4 Using where; Using index 1 PRIMARY t2 index NULL PRIMARY 4 NULL 4 Using where; Using index
2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 Using where 2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 Using where
Warnings: Warnings:
Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(<primary_index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on PRIMARY where (`test`.`t1`.`b` <> 30)))) Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(<primary_index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on PRIMARY where ((`test`.`t1`.`b` <> 30) and (<cache>(`test`.`t2`.`a`) = `test`.`t1`.`a`)))))
select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a); select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
a a
2 2
...@@ -1315,8 +1315,8 @@ a ...@@ -1315,8 +1315,8 @@ a
explain extended select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a); explain extended select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.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 PRIMARY t2 index NULL PRIMARY 4 NULL 4 Using where; Using index 1 PRIMARY t2 index NULL PRIMARY 4 NULL 4 Using where; Using index
2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 func 1 Using where 2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 func 1
2 DEPENDENT SUBQUERY t3 eq_ref PRIMARY PRIMARY 4 test.t1.b 1 Using where; Using index 2 DEPENDENT SUBQUERY t3 eq_ref PRIMARY PRIMARY 4 test.t1.b 1 Using index
Warnings: Warnings:
Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(select 1 AS `Not_used` from `test`.`t1` join `test`.`t3` where ((`test`.`t3`.`a` = `test`.`t1`.`b`) and (<cache>(`test`.`t2`.`a`) = `test`.`t1`.`a`)))) Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(select 1 AS `Not_used` from `test`.`t1` join `test`.`t3` where ((`test`.`t3`.`a` = `test`.`t1`.`b`) and (<cache>(`test`.`t2`.`a`) = `test`.`t1`.`a`))))
drop table t1, t2, t3; drop table t1, t2, t3;
...@@ -1334,9 +1334,9 @@ a ...@@ -1334,9 +1334,9 @@ a
explain extended select * from t2 where t2.a in (select a from t1); explain extended select * from t2 where t2.a in (select a from t1);
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 PRIMARY t2 index NULL a 5 NULL 4 Using where; Using index 1 PRIMARY t2 index NULL a 5 NULL 4 Using where; Using index
2 DEPENDENT SUBQUERY t1 index_subquery a a 5 func 1001 Using index 2 DEPENDENT SUBQUERY t1 index_subquery a a 5 func 1001 Using index; Using where
Warnings: Warnings:
Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on a))) Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on a where (<cache>(`test`.`t2`.`a`) = `test`.`t1`.`a`))))
select * from t2 where t2.a in (select a from t1 where t1.b <> 30); select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
a a
2 2
...@@ -1346,7 +1346,7 @@ id select_type table type possible_keys key key_len ref rows Extra ...@@ -1346,7 +1346,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 index NULL a 5 NULL 4 Using where; Using index 1 PRIMARY t2 index NULL a 5 NULL 4 Using where; Using index
2 DEPENDENT SUBQUERY t1 index_subquery a a 5 func 1001 Using index; Using where 2 DEPENDENT SUBQUERY t1 index_subquery a a 5 func 1001 Using index; Using where
Warnings: Warnings:
Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on a where (`test`.`t1`.`b` <> 30)))) Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on a where ((`test`.`t1`.`b` <> 30) and (<cache>(`test`.`t2`.`a`) = `test`.`t1`.`a`)))))
select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a); select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
a a
2 2
...@@ -1373,7 +1373,7 @@ id select_type table type possible_keys key key_len ref rows Extra ...@@ -1373,7 +1373,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 index NULL a 5 NULL 4 Using where; Using index 1 PRIMARY t2 index NULL a 5 NULL 4 Using where; Using index
2 DEPENDENT SUBQUERY t1 index_subquery a a 5 func 1001 Using index; Using where 2 DEPENDENT SUBQUERY t1 index_subquery a a 5 func 1001 Using index; Using where
Warnings: Warnings:
Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on a where (`test`.`t1`.`b` <> 30)))) Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on a where ((`test`.`t1`.`b` <> 30) and (<cache>(`test`.`t2`.`a`) = `test`.`t1`.`a`)))))
drop table t1, t2, t3; drop table t1, t2, t3;
create table t1 (a int, b int); create table t1 (a int, b int);
create table t2 (a int, b int); create table t2 (a int, b int);
...@@ -1737,7 +1737,7 @@ id select_type table type possible_keys key key_len ref rows Extra ...@@ -1737,7 +1737,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 12 Using where 1 PRIMARY t1 ALL NULL NULL NULL NULL 12 Using where
2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 Using index; Using where 2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 Using index; Using where
Warnings: Warnings:
Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `test`.`t1` where (not(<in_optimizer>(`test`.`t1`.`id`,<exists>(<primary_index_lookup>(<cache>(`test`.`t1`.`id`) in t1 on PRIMARY where (`test`.`t1`.`id` < 8)))))) Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `test`.`t1` where (not(<in_optimizer>(`test`.`t1`.`id`,<exists>(<primary_index_lookup>(<cache>(`test`.`t1`.`id`) in t1 on PRIMARY where ((`test`.`t1`.`id` < 8) and (<cache>(`test`.`t1`.`id`) = `test`.`t1`.`id`)))))))
explain extended select * from t1 as tt where not exists (select id from t1 where id < 8 and (id = tt.id or id is null) having id is not null); explain extended select * from t1 as tt where not exists (select id from t1 where id < 8 and (id = tt.id or id is null) having id is not 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 PRIMARY tt ALL NULL NULL NULL NULL 12 Using where 1 PRIMARY tt ALL NULL NULL NULL NULL 12 Using where
...@@ -4303,4 +4303,35 @@ LEFT(t1.a1,1) ...@@ -4303,4 +4303,35 @@ LEFT(t1.a1,1)
SELECT a2 FROM t2 WHERE t2.a2 IN (SELECT t1.a1 FROM t1,t3 WHERE t1.b1=t3.a3); SELECT a2 FROM t2 WHERE t2.a2 IN (SELECT t1.a1 FROM t1,t3 WHERE t1.b1=t3.a3);
a2 a2
DROP TABLE t1, t2, t3; DROP TABLE t1, t2, t3;
CREATE TABLE t1 (a CHAR(1), b VARCHAR(10));
INSERT INTO t1 VALUES ('a', 'aa');
INSERT INTO t1 VALUES ('a', 'aaa');
SELECT a,b FROM t1 WHERE b IN (SELECT a FROM t1);
a b
CREATE INDEX I1 ON t1 (a);
CREATE INDEX I2 ON t1 (b);
EXPLAIN SELECT a,b FROM t1 WHERE b IN (SELECT a FROM t1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
2 DEPENDENT SUBQUERY t1 index_subquery I1 I1 2 func 2 Using index; Using where
SELECT a,b FROM t1 WHERE b IN (SELECT a FROM t1);
a b
CREATE TABLE t2 (a VARCHAR(1), b VARCHAR(10));
INSERT INTO t2 SELECT * FROM t1;
CREATE INDEX I1 ON t2 (a);
CREATE INDEX I2 ON t2 (b);
EXPLAIN SELECT a,b FROM t2 WHERE b IN (SELECT a FROM t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where
2 DEPENDENT SUBQUERY t2 index_subquery I1 I1 4 func 2 Using index; Using where
SELECT a,b FROM t2 WHERE b IN (SELECT a FROM t2);
a b
EXPLAIN
SELECT a,b FROM t1 WHERE b IN (SELECT a FROM t1 WHERE LENGTH(a)<500);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
2 DEPENDENT SUBQUERY t1 index_subquery I1 I1 2 func 2 Using index; Using where
SELECT a,b FROM t1 WHERE b IN (SELECT a FROM t1 WHERE LENGTH(a)<500);
a b
DROP TABLE t1,t2;
End of 5.0 tests. End of 5.0 tests.
...@@ -757,6 +757,6 @@ a ...@@ -757,6 +757,6 @@ a
EXPLAIN SELECT a FROM t1 WHERE a NOT IN (SELECT a FROM t2); EXPLAIN SELECT a FROM t1 WHERE a NOT IN (SELECT a FROM t2);
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 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where 1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where
2 DEPENDENT SUBQUERY t2 unique_subquery PRIMARY PRIMARY 4 func 1 Using index 2 DEPENDENT SUBQUERY t2 unique_subquery PRIMARY PRIMARY 4 func 1 Using index; Using where
DROP TABLE t1; DROP TABLE t1;
End of 5.0 tests End of 5.0 tests
...@@ -3140,4 +3140,29 @@ SELECT LEFT(t1.a1,1) FROM t1,t3 WHERE t1.b1=t3.a3; ...@@ -3140,4 +3140,29 @@ SELECT LEFT(t1.a1,1) FROM t1,t3 WHERE t1.b1=t3.a3;
SELECT a2 FROM t2 WHERE t2.a2 IN (SELECT t1.a1 FROM t1,t3 WHERE t1.b1=t3.a3); SELECT a2 FROM t2 WHERE t2.a2 IN (SELECT t1.a1 FROM t1,t3 WHERE t1.b1=t3.a3);
DROP TABLE t1, t2, t3; DROP TABLE t1, t2, t3;
#
# Bug #30788: Inconsistent retrieval of char/varchar
#
CREATE TABLE t1 (a CHAR(1), b VARCHAR(10));
INSERT INTO t1 VALUES ('a', 'aa');
INSERT INTO t1 VALUES ('a', 'aaa');
SELECT a,b FROM t1 WHERE b IN (SELECT a FROM t1);
CREATE INDEX I1 ON t1 (a);
CREATE INDEX I2 ON t1 (b);
EXPLAIN SELECT a,b FROM t1 WHERE b IN (SELECT a FROM t1);
SELECT a,b FROM t1 WHERE b IN (SELECT a FROM t1);
CREATE TABLE t2 (a VARCHAR(1), b VARCHAR(10));
INSERT INTO t2 SELECT * FROM t1;
CREATE INDEX I1 ON t2 (a);
CREATE INDEX I2 ON t2 (b);
EXPLAIN SELECT a,b FROM t2 WHERE b IN (SELECT a FROM t2);
SELECT a,b FROM t2 WHERE b IN (SELECT a FROM t2);
EXPLAIN
SELECT a,b FROM t1 WHERE b IN (SELECT a FROM t1 WHERE LENGTH(a)<500);
SELECT a,b FROM t1 WHERE b IN (SELECT a FROM t1 WHERE LENGTH(a)<500);
DROP TABLE t1,t2;
--echo End of 5.0 tests. --echo End of 5.0 tests.
...@@ -2452,8 +2452,18 @@ class Item_cache: public Item ...@@ -2452,8 +2452,18 @@ class Item_cache: public Item
protected: protected:
Item *example; Item *example;
table_map used_table_map; table_map used_table_map;
/*
Field that this object will get value from. This is set/used by
index-based subquery engines to detect and remove the equality injected
by IN->EXISTS transformation.
For all other uses of Item_cache, cached_field doesn't matter.
*/
Field *cached_field;
public: public:
Item_cache(): example(0), used_table_map(0) {fixed= 1; null_value= 1;} Item_cache(): example(0), used_table_map(0), cached_field(0)
{
fixed= 1; null_value= 1;
}
void set_used_tables(table_map map) { used_table_map= map; } void set_used_tables(table_map map) { used_table_map= map; }
...@@ -2465,6 +2475,8 @@ public: ...@@ -2465,6 +2475,8 @@ public:
decimals= item->decimals; decimals= item->decimals;
collation.set(item->collation); collation.set(item->collation);
unsigned_flag= item->unsigned_flag; unsigned_flag= item->unsigned_flag;
if (item->type() == FIELD_ITEM)
cached_field= ((Item_field *)item)->field;
return 0; return 0;
}; };
virtual void store(Item *)= 0; virtual void store(Item *)= 0;
...@@ -2475,6 +2487,14 @@ public: ...@@ -2475,6 +2487,14 @@ public:
// to prevent drop fixed flag (no need parent cleanup call) // to prevent drop fixed flag (no need parent cleanup call)
void cleanup() {} void cleanup() {}
void print(String *str); void print(String *str);
bool eq_def(Field *field)
{
return cached_field ? cached_field->eq_def (field) : FALSE;
}
bool eq(const Item *item, bool binary_cmp) const
{
return this == item;
}
}; };
......
...@@ -217,6 +217,7 @@ static void select_describe(JOIN *join, bool need_tmp_table,bool need_order, ...@@ -217,6 +217,7 @@ static void select_describe(JOIN *join, bool need_tmp_table,bool need_order,
bool distinct, const char *message=NullS); bool distinct, const char *message=NullS);
static Item *remove_additional_cond(Item* conds); static Item *remove_additional_cond(Item* conds);
static void add_group_and_distinct_keys(JOIN *join, JOIN_TAB *join_tab); static void add_group_and_distinct_keys(JOIN *join, JOIN_TAB *join_tab);
static bool test_if_ref(Item_field *left_item,Item *right_item);
/* /*
...@@ -681,9 +682,6 @@ err: ...@@ -681,9 +682,6 @@ err:
without "checking NULL", remove the predicates that were pushed down without "checking NULL", remove the predicates that were pushed down
into the subquery. into the subquery.
We can remove the equalities that will be guaranteed to be true by the
fact that subquery engine will be using index lookup.
If the subquery compares scalar values, we can remove the condition that If the subquery compares scalar values, we can remove the condition that
was wrapped into trig_cond (it will be checked when needed by the subquery was wrapped into trig_cond (it will be checked when needed by the subquery
engine) engine)
...@@ -693,6 +691,12 @@ err: ...@@ -693,6 +691,12 @@ err:
and non-NULL values, we'll do a full table scan and will rely on the and non-NULL values, we'll do a full table scan and will rely on the
equalities corresponding to non-NULL parts of left tuple to filter out equalities corresponding to non-NULL parts of left tuple to filter out
non-matching records. non-matching records.
TODO: We can remove the equalities that will be guaranteed to be true by the
fact that subquery engine will be using index lookup. This must be done only
for cases where there are no conversion errors of significance, e.g. 257
that is searched in a byte. But this requires homogenization of the return
codes of all Field*::store() methods.
*/ */
void JOIN::remove_subq_pushed_predicates(Item **where) void JOIN::remove_subq_pushed_predicates(Item **where)
...@@ -700,17 +704,13 @@ void JOIN::remove_subq_pushed_predicates(Item **where) ...@@ -700,17 +704,13 @@ void JOIN::remove_subq_pushed_predicates(Item **where)
if (conds->type() == Item::FUNC_ITEM && if (conds->type() == Item::FUNC_ITEM &&
((Item_func *)this->conds)->functype() == Item_func::EQ_FUNC && ((Item_func *)this->conds)->functype() == Item_func::EQ_FUNC &&
((Item_func *)conds)->arguments()[0]->type() == Item::REF_ITEM && ((Item_func *)conds)->arguments()[0]->type() == Item::REF_ITEM &&
((Item_func *)conds)->arguments()[1]->type() == Item::FIELD_ITEM) ((Item_func *)conds)->arguments()[1]->type() == Item::FIELD_ITEM &&
test_if_ref ((Item_field *)((Item_func *)conds)->arguments()[1],
((Item_func *)conds)->arguments()[0]))
{ {
*where= 0; *where= 0;
return; return;
} }
if (conds->type() == Item::COND_ITEM &&
((class Item_func *)this->conds)->functype() ==
Item_func::COND_AND_FUNC)
{
*where= remove_additional_cond(conds);
}
} }
...@@ -1236,7 +1236,7 @@ JOIN::optimize() ...@@ -1236,7 +1236,7 @@ JOIN::optimize()
{ {
if (!having) if (!having)
{ {
Item *where= 0; Item *where= conds;
if (join_tab[0].type == JT_EQ_REF && if (join_tab[0].type == JT_EQ_REF &&
join_tab[0].ref.items[0]->name == in_left_expr_name) join_tab[0].ref.items[0]->name == in_left_expr_name)
{ {
...@@ -11892,8 +11892,12 @@ static bool test_if_ref(Item_field *left_item,Item *right_item) ...@@ -11892,8 +11892,12 @@ static bool test_if_ref(Item_field *left_item,Item *right_item)
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))
{ {
right_item= right_item->real_item();
if (right_item->type() == Item::FIELD_ITEM) if (right_item->type() == Item::FIELD_ITEM)
return (field->eq_def(((Item_field *) right_item)->field)); return (field->eq_def(((Item_field *) right_item)->field));
/* remove equalities injected by IN->EXISTS transformation */
else if (right_item->type() == Item::CACHE_ITEM)
return ((Item_cache *)right_item)->eq_def (field);
if (right_item->const_item() && !(right_item->is_null())) if (right_item->const_item() && !(right_item->is_null()))
{ {
/* /*
......
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