Commit 5819dfcd authored by Igor Babaev's avatar Igor Babaev

Fixed LP bug #809206.

The bitmap of used tables must be evaluated for the select list of every
materialized derived table / view and saved in a dedicated field.
This is also applied to materialized subqueries.
parent 419c20f1
...@@ -946,7 +946,7 @@ DROP TABLE t1,t2,t3; ...@@ -946,7 +946,7 @@ DROP TABLE t1,t2,t3;
# LP bug #806504: right join over a view/derived table # LP bug #806504: right join over a view/derived table
# #
CREATE TABLE t1 (a int, b int) ; CREATE TABLE t1 (a int, b int) ;
INSERT IGNORE INTO t1 VALUES (0,0); INSERT INTO t1 VALUES (0,0);
CREATE TABLE t2 (a int) ; CREATE TABLE t2 (a int) ;
INSERT INTO t2 VALUES (0), (0); INSERT INTO t2 VALUES (0), (0);
CREATE VIEW v1 AS SELECT * FROM t1; CREATE VIEW v1 AS SELECT * FROM t1;
...@@ -978,3 +978,49 @@ Warnings: ...@@ -978,3 +978,49 @@ Warnings:
Note 1003 select `test`.`t2`.`a` AS `a`,0 AS `a`,0 AS `b` from `test`.`t1` left join `test`.`t2` on((0 <> 0)) where <expr_cache><0>(<in_optimizer>(0,<exists>(select 0 from `test`.`t1` where (<cache>(0) = 0)))) Note 1003 select `test`.`t2`.`a` AS `a`,0 AS `a`,0 AS `b` from `test`.`t1` left join `test`.`t2` on((0 <> 0)) where <expr_cache><0>(<in_optimizer>(0,<exists>(select 0 from `test`.`t1` where (<cache>(0) = 0))))
DROP VIEW v1; DROP VIEW v1;
DROP TABLE t1,t2; DROP TABLE t1,t2;
#
# LP bug #809206: DISTINCT in derived table / view
#
CREATE TABLE t1 (a int) ;
INSERT INTO t1 VALUES (0);
CREATE TABLE t2 (a varchar(32), b int, KEY (a)) ;
INSERT INTO t2 VALUES
('j',28), ('c',29), ('i',26), ('c',29), ('k',27),
('j',28), ('c',29), ('i',25), ('d',26), ('k',27);
CREATE TABLE t3 (a varchar(32));
INSERT INTO t3 VALUES ('j'), ('c');
CREATE VIEW v1 AS SELECT DISTINCT t2.b FROM t1,t2,t3 WHERE t3.a = t2.a;
SELECT DISTINCT t2.b FROM t1,t2,t3 WHERE t3.a = t2.a;
b
28
29
EXPLAIN
SELECT DISTINCT t2.b FROM t1,t2,t3 WHERE t3.a = t2.a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 system NULL NULL NULL NULL 1 Using temporary
1 SIMPLE t3 ALL NULL NULL NULL NULL 2 Using where
1 SIMPLE t2 ref a a 35 test.t3.a 2
SELECT * FROM (SELECT DISTINCT t2.b FROM t1,t2,t3 WHERE t3.a = t2.a) t;
b
28
29
EXPLAIN
SELECT * FROM (SELECT DISTINCT t2.b FROM t1,t2,t3 WHERE t3.a = t2.a) t;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4
2 DERIVED t1 system NULL NULL NULL NULL 1 Using temporary
2 DERIVED t3 ALL NULL NULL NULL NULL 2 Using where
2 DERIVED t2 ref a a 35 test.t3.a 2
SELECT * FROM v1;
b
28
29
EXPLAIN
SELECT * FROM v1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4
2 DERIVED t1 system NULL NULL NULL NULL 1 Using temporary
2 DERIVED t3 ALL NULL NULL NULL NULL 2 Using where
2 DERIVED t2 ref a a 35 test.t3.a 2
DROP VIEW v1;
DROP TABLE t1,t2,t3;
...@@ -985,8 +985,8 @@ EXPLAIN EXTENDED SELECT 1 FROM ...@@ -985,8 +985,8 @@ EXPLAIN EXTENDED SELECT 1 FROM
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 ALL NULL NULL NULL NULL 2 100.00 1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4 100.00 Using join buffer (flat, BNL join) 1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4 100.00 Using join buffer (flat, BNL join)
2 DERIVED t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort; Distinct 2 DERIVED t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
2 DERIVED td ALL NULL NULL NULL NULL 2 100.00 Distinct; Using join buffer (flat, BNL join) 2 DERIVED td ALL NULL NULL NULL NULL 2 100.00 Using join buffer (flat, BNL join)
Warnings: Warnings:
Note 1003 select 1 AS `1` from (select distinct group_concat(`test`.`td`.`f1` separator ',') AS `GROUP_CONCAT(td.f1)` from `test`.`t1` join `test`.`t1` `td` group by `test`.`td`.`f1`) `d` join `test`.`t1` Note 1003 select 1 AS `1` from (select distinct group_concat(`test`.`td`.`f1` separator ',') AS `GROUP_CONCAT(td.f1)` from `test`.`t1` join `test`.`t1` `td` group by `test`.`td`.`f1`) `d` join `test`.`t1`
SELECT 1 FROM SELECT 1 FROM
......
...@@ -537,7 +537,7 @@ DROP TABLE t1,t2,t3; ...@@ -537,7 +537,7 @@ DROP TABLE t1,t2,t3;
--echo # --echo #
CREATE TABLE t1 (a int, b int) ; CREATE TABLE t1 (a int, b int) ;
INSERT IGNORE INTO t1 VALUES (0,0); INSERT INTO t1 VALUES (0,0);
CREATE TABLE t2 (a int) ; CREATE TABLE t2 (a int) ;
INSERT INTO t2 VALUES (0), (0); INSERT INTO t2 VALUES (0), (0);
...@@ -558,3 +558,35 @@ SELECT * FROM t2 RIGHT JOIN v1 AS t ON t.a != 0 ...@@ -558,3 +558,35 @@ SELECT * FROM t2 RIGHT JOIN v1 AS t ON t.a != 0
DROP VIEW v1; DROP VIEW v1;
DROP TABLE t1,t2; DROP TABLE t1,t2;
--echo #
--echo # LP bug #809206: DISTINCT in derived table / view
--echo #
CREATE TABLE t1 (a int) ;
INSERT INTO t1 VALUES (0);
CREATE TABLE t2 (a varchar(32), b int, KEY (a)) ;
INSERT INTO t2 VALUES
('j',28), ('c',29), ('i',26), ('c',29), ('k',27),
('j',28), ('c',29), ('i',25), ('d',26), ('k',27);
CREATE TABLE t3 (a varchar(32));
INSERT INTO t3 VALUES ('j'), ('c');
CREATE VIEW v1 AS SELECT DISTINCT t2.b FROM t1,t2,t3 WHERE t3.a = t2.a;
SELECT DISTINCT t2.b FROM t1,t2,t3 WHERE t3.a = t2.a;
EXPLAIN
SELECT DISTINCT t2.b FROM t1,t2,t3 WHERE t3.a = t2.a;
SELECT * FROM (SELECT DISTINCT t2.b FROM t1,t2,t3 WHERE t3.a = t2.a) t;
EXPLAIN
SELECT * FROM (SELECT DISTINCT t2.b FROM t1,t2,t3 WHERE t3.a = t2.a) t;
SELECT * FROM v1;
EXPLAIN
SELECT * FROM v1;
DROP VIEW v1;
DROP TABLE t1,t2,t3;
...@@ -3511,7 +3511,6 @@ void SELECT_LEX::update_used_tables() ...@@ -3511,7 +3511,6 @@ void SELECT_LEX::update_used_tables()
while ((item= it++)) while ((item= it++))
{ {
item->update_used_tables(); item->update_used_tables();
join->thd->used_tables|= item->used_tables();
} }
Item_outer_ref *ref; Item_outer_ref *ref;
List_iterator_fast<Item_outer_ref> ref_it(inner_refs_list); List_iterator_fast<Item_outer_ref> ref_it(inner_refs_list);
...@@ -3519,7 +3518,6 @@ void SELECT_LEX::update_used_tables() ...@@ -3519,7 +3518,6 @@ void SELECT_LEX::update_used_tables()
{ {
item= ref->outer_ref; item= ref->outer_ref;
item->update_used_tables(); item->update_used_tables();
join->thd->used_tables|= item->used_tables();
} }
for (ORDER *order= group_list.first; order; order= order->next) for (ORDER *order= group_list.first; order; order= order->next)
(*order->item)->update_used_tables(); (*order->item)->update_used_tables();
......
...@@ -880,8 +880,6 @@ JOIN::optimize() ...@@ -880,8 +880,6 @@ JOIN::optimize()
if (select_lex->first_cond_optimization) if (select_lex->first_cond_optimization)
{ {
if (!select_lex->outer_select())
thd->used_tables= 0;
//Do it only for the first execution //Do it only for the first execution
/* Merge all mergeable derived tables/views in this SELECT. */ /* Merge all mergeable derived tables/views in this SELECT. */
if (select_lex->handle_derived(thd->lex, DT_MERGE)) if (select_lex->handle_derived(thd->lex, DT_MERGE))
...@@ -895,8 +893,6 @@ JOIN::optimize() ...@@ -895,8 +893,6 @@ JOIN::optimize()
if (select_lex->first_cond_optimization) if (select_lex->first_cond_optimization)
{ {
if (!select_lex->outer_select())
thd->used_tables= 0;
/* dump_TABLE_LIST_graph(select_lex, select_lex->leaf_tables); */ /* dump_TABLE_LIST_graph(select_lex, select_lex->leaf_tables); */
if (convert_join_subqueries_to_semijoins(this)) if (convert_join_subqueries_to_semijoins(this))
DBUG_RETURN(1); /* purecov: inspected */ DBUG_RETURN(1); /* purecov: inspected */
...@@ -906,6 +902,7 @@ JOIN::optimize() ...@@ -906,6 +902,7 @@ JOIN::optimize()
/* Save this info for the next executions */ /* Save this info for the next executions */
if (select_lex->save_leaf_tables(thd)) if (select_lex->save_leaf_tables(thd))
DBUG_RETURN(1); DBUG_RETURN(1);
eval_select_list_used_tables();
} }
table_count= select_lex->leaf_tables.elements; table_count= select_lex->leaf_tables.elements;
...@@ -1727,7 +1724,7 @@ int JOIN::init_execution() ...@@ -1727,7 +1724,7 @@ int JOIN::init_execution()
if (exec_tmp_table1->distinct) if (exec_tmp_table1->distinct)
{ {
table_map used_tables= thd->used_tables; table_map used_tables= select_list_used_tables;
JOIN_TAB *last_join_tab= join_tab + top_join_tab_count - 1; JOIN_TAB *last_join_tab= join_tab + top_join_tab_count - 1;
do do
{ {
...@@ -8464,6 +8461,30 @@ void JOIN::drop_unused_derived_keys() ...@@ -8464,6 +8461,30 @@ void JOIN::drop_unused_derived_keys()
} }
} }
/*
Evaluate the bitmap of used tables for items from the select list
*/
inline void JOIN::eval_select_list_used_tables()
{
select_list_used_tables= 0;
Item *item;
List_iterator_fast<Item> it(fields_list);
while ((item= it++))
{
select_list_used_tables|= item->used_tables();
}
Item_outer_ref *ref;
List_iterator_fast<Item_outer_ref> ref_it(select_lex->inner_refs_list);
while ((ref= ref_it++))
{
item= ref->outer_ref;
select_list_used_tables|= item->used_tables();
}
}
/* /*
Determine {after which table we'll produce ordered set} Determine {after which table we'll produce ordered set}
...@@ -20845,7 +20866,8 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, ...@@ -20845,7 +20866,8 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
need_order=0; need_order=0;
extra.append(STRING_WITH_LEN("; Using filesort")); extra.append(STRING_WITH_LEN("; Using filesort"));
} }
if (distinct & test_all_bits(used_tables,thd->used_tables)) if (distinct & test_all_bits(used_tables,
join->select_list_used_tables))
extra.append(STRING_WITH_LEN("; Distinct")); extra.append(STRING_WITH_LEN("; Distinct"));
if (tab->loosescan_match_tab) if (tab->loosescan_match_tab)
{ {
......
...@@ -767,6 +767,8 @@ class JOIN :public Sql_alloc ...@@ -767,6 +767,8 @@ class JOIN :public Sql_alloc
make_join_statistics) make_join_statistics)
*/ */
table_map outer_join; table_map outer_join;
/* Bitmap of tables used in the select list items */
table_map select_list_used_tables;
ha_rows send_records,found_records,examined_rows,row_limit, select_limit; ha_rows send_records,found_records,examined_rows,row_limit, select_limit;
/** /**
Used to fetch no more than given amount of rows per one Used to fetch no more than given amount of rows per one
...@@ -1134,6 +1136,7 @@ class JOIN :public Sql_alloc ...@@ -1134,6 +1136,7 @@ class JOIN :public Sql_alloc
return (table_map(1) << table_count) - 1; return (table_map(1) << table_count) - 1;
} }
void drop_unused_derived_keys(); void drop_unused_derived_keys();
inline void eval_select_list_used_tables();
/* /*
Return the table for which an index scan can be used to satisfy Return the table for which an index scan can be used to satisfy
the sort order needed by the ORDER BY/(implicit) GROUP BY clause the sort order needed by the ORDER BY/(implicit) GROUP BY clause
......
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