mirror of
https://github.com/MariaDB/server.git
synced 2025-01-26 16:54:15 +01:00
MWL#89: Cost-based choice between Materialization and IN->EXISTS transformation
Added missing logic to handle the case when subquery tables are optimized away early during optimization.
This commit is contained in:
parent
e85a4cb6b5
commit
f670b6d22f
7 changed files with 284 additions and 67 deletions
|
@ -123,13 +123,13 @@ select a1 from t1 where a1 in (select b1 from t2 where b1 = b2 and b2 = '1 - 03'
|
||||||
-- echo /* E.5 opt_sum_query detects no matching min/max row or substitutes MIN/MAX with a const. */
|
-- echo /* E.5 opt_sum_query detects no matching min/max row or substitutes MIN/MAX with a const. */
|
||||||
-- echo TODO this test produces wrong result due to missing logic to handle the case
|
-- echo TODO this test produces wrong result due to missing logic to handle the case
|
||||||
-- echo when JOIN::optimize detects an empty subquery result.
|
-- echo when JOIN::optimize detects an empty subquery result.
|
||||||
#explain
|
explain
|
||||||
#select a1 from t1 where a1 in (select max(b1) from t2);
|
select a1 from t1 where a1 in (select max(b1) from t2);
|
||||||
#select a1 from t1 where a1 in (select max(b1) from t2);
|
select a1 from t1 where a1 in (select max(b1) from t2);
|
||||||
-- echo
|
-- echo
|
||||||
#explain
|
explain
|
||||||
#select a1 from t1 where a1 in (select max(b1) from t2 where b1 = '7 - 02');
|
select a1 from t1 where a1 in (select max(b1) from t2 where b1 = '7 - 02');
|
||||||
#select a1 from t1 where a1 in (select max(b1) from t2 where b1 = '7 - 02');
|
select a1 from t1 where a1 in (select max(b1) from t2 where b1 = '7 - 02');
|
||||||
|
|
||||||
-- echo /* E.6 make_join_select detects impossible WHERE. *
|
-- echo /* E.6 make_join_select detects impossible WHERE. *
|
||||||
|
|
||||||
|
|
|
@ -342,7 +342,21 @@ a1
|
||||||
/* E.5 opt_sum_query detects no matching min/max row or substitutes MIN/MAX with a const. */
|
/* E.5 opt_sum_query detects no matching min/max row or substitutes MIN/MAX with a const. */
|
||||||
TODO this test produces wrong result due to missing logic to handle the case
|
TODO this test produces wrong result due to missing logic to handle the case
|
||||||
when JOIN::optimize detects an empty subquery result.
|
when JOIN::optimize detects an empty subquery result.
|
||||||
|
explain
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2);
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 index NULL it1i1 9 NULL 3 Using where; Using index
|
||||||
|
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 5
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2);
|
||||||
|
a1
|
||||||
|
|
||||||
|
explain
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2 where b1 = '7 - 02');
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 index NULL it1i1 9 NULL 3 Using where; Using index
|
||||||
|
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 5 Using where
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2 where b1 = '7 - 02');
|
||||||
|
a1
|
||||||
/* E.6 make_join_select detects impossible WHERE. *
|
/* E.6 make_join_select detects impossible WHERE. *
|
||||||
TODO
|
TODO
|
||||||
/* E.7 constant optimization detects "no matching row in const table". */
|
/* E.7 constant optimization detects "no matching row in const table". */
|
||||||
|
@ -609,7 +623,21 @@ a1
|
||||||
/* E.5 opt_sum_query detects no matching min/max row or substitutes MIN/MAX with a const. */
|
/* E.5 opt_sum_query detects no matching min/max row or substitutes MIN/MAX with a const. */
|
||||||
TODO this test produces wrong result due to missing logic to handle the case
|
TODO this test produces wrong result due to missing logic to handle the case
|
||||||
when JOIN::optimize detects an empty subquery result.
|
when JOIN::optimize detects an empty subquery result.
|
||||||
|
explain
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2);
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 index NULL it1i1 9 NULL 3 Using where; Using index
|
||||||
|
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2);
|
||||||
|
a1
|
||||||
|
|
||||||
|
explain
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2 where b1 = '7 - 02');
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 index NULL it1i1 9 NULL 3 Using where; Using index
|
||||||
|
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL No matching min/max row
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2 where b1 = '7 - 02');
|
||||||
|
a1
|
||||||
/* E.6 make_join_select detects impossible WHERE. *
|
/* E.6 make_join_select detects impossible WHERE. *
|
||||||
TODO
|
TODO
|
||||||
/* E.7 constant optimization detects "no matching row in const table". */
|
/* E.7 constant optimization detects "no matching row in const table". */
|
||||||
|
@ -876,7 +904,21 @@ a1
|
||||||
/* E.5 opt_sum_query detects no matching min/max row or substitutes MIN/MAX with a const. */
|
/* E.5 opt_sum_query detects no matching min/max row or substitutes MIN/MAX with a const. */
|
||||||
TODO this test produces wrong result due to missing logic to handle the case
|
TODO this test produces wrong result due to missing logic to handle the case
|
||||||
when JOIN::optimize detects an empty subquery result.
|
when JOIN::optimize detects an empty subquery result.
|
||||||
|
explain
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2);
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 index NULL it1i1 8 NULL 3 Using where; Using index
|
||||||
|
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2);
|
||||||
|
a1
|
||||||
|
|
||||||
|
explain
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2 where b1 = '7 - 02');
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 index NULL it1i1 8 NULL 3 Using where; Using index
|
||||||
|
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL No matching min/max row
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2 where b1 = '7 - 02');
|
||||||
|
a1
|
||||||
/* E.6 make_join_select detects impossible WHERE. *
|
/* E.6 make_join_select detects impossible WHERE. *
|
||||||
TODO
|
TODO
|
||||||
/* E.7 constant optimization detects "no matching row in const table". */
|
/* E.7 constant optimization detects "no matching row in const table". */
|
||||||
|
@ -1193,7 +1235,22 @@ a1
|
||||||
/* E.5 opt_sum_query detects no matching min/max row or substitutes MIN/MAX with a const. */
|
/* E.5 opt_sum_query detects no matching min/max row or substitutes MIN/MAX with a const. */
|
||||||
TODO this test produces wrong result due to missing logic to handle the case
|
TODO this test produces wrong result due to missing logic to handle the case
|
||||||
when JOIN::optimize detects an empty subquery result.
|
when JOIN::optimize detects an empty subquery result.
|
||||||
|
explain
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2);
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where
|
||||||
|
2 SUBQUERY t2 ALL NULL NULL NULL NULL 5
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2);
|
||||||
|
a1
|
||||||
|
1 - 03
|
||||||
|
|
||||||
|
explain
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2 where b1 = '7 - 02');
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where
|
||||||
|
2 SUBQUERY t2 ALL NULL NULL NULL NULL 5 Using where
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2 where b1 = '7 - 02');
|
||||||
|
a1
|
||||||
/* E.6 make_join_select detects impossible WHERE. *
|
/* E.6 make_join_select detects impossible WHERE. *
|
||||||
TODO
|
TODO
|
||||||
/* E.7 constant optimization detects "no matching row in const table". */
|
/* E.7 constant optimization detects "no matching row in const table". */
|
||||||
|
@ -1505,7 +1562,22 @@ a1
|
||||||
/* E.5 opt_sum_query detects no matching min/max row or substitutes MIN/MAX with a const. */
|
/* E.5 opt_sum_query detects no matching min/max row or substitutes MIN/MAX with a const. */
|
||||||
TODO this test produces wrong result due to missing logic to handle the case
|
TODO this test produces wrong result due to missing logic to handle the case
|
||||||
when JOIN::optimize detects an empty subquery result.
|
when JOIN::optimize detects an empty subquery result.
|
||||||
|
explain
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2);
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where
|
||||||
|
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2);
|
||||||
|
a1
|
||||||
|
1 - 03
|
||||||
|
|
||||||
|
explain
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2 where b1 = '7 - 02');
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where
|
||||||
|
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL No matching min/max row
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2 where b1 = '7 - 02');
|
||||||
|
a1
|
||||||
/* E.6 make_join_select detects impossible WHERE. *
|
/* E.6 make_join_select detects impossible WHERE. *
|
||||||
TODO
|
TODO
|
||||||
/* E.7 constant optimization detects "no matching row in const table". */
|
/* E.7 constant optimization detects "no matching row in const table". */
|
||||||
|
@ -1817,7 +1889,22 @@ a1
|
||||||
/* E.5 opt_sum_query detects no matching min/max row or substitutes MIN/MAX with a const. */
|
/* E.5 opt_sum_query detects no matching min/max row or substitutes MIN/MAX with a const. */
|
||||||
TODO this test produces wrong result due to missing logic to handle the case
|
TODO this test produces wrong result due to missing logic to handle the case
|
||||||
when JOIN::optimize detects an empty subquery result.
|
when JOIN::optimize detects an empty subquery result.
|
||||||
|
explain
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2);
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where
|
||||||
|
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2);
|
||||||
|
a1
|
||||||
|
1 - 03
|
||||||
|
|
||||||
|
explain
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2 where b1 = '7 - 02');
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where
|
||||||
|
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL No matching min/max row
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2 where b1 = '7 - 02');
|
||||||
|
a1
|
||||||
/* E.6 make_join_select detects impossible WHERE. *
|
/* E.6 make_join_select detects impossible WHERE. *
|
||||||
TODO
|
TODO
|
||||||
/* E.7 constant optimization detects "no matching row in const table". */
|
/* E.7 constant optimization detects "no matching row in const table". */
|
||||||
|
@ -2134,7 +2221,22 @@ a1
|
||||||
/* E.5 opt_sum_query detects no matching min/max row or substitutes MIN/MAX with a const. */
|
/* E.5 opt_sum_query detects no matching min/max row or substitutes MIN/MAX with a const. */
|
||||||
TODO this test produces wrong result due to missing logic to handle the case
|
TODO this test produces wrong result due to missing logic to handle the case
|
||||||
when JOIN::optimize detects an empty subquery result.
|
when JOIN::optimize detects an empty subquery result.
|
||||||
|
explain
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2);
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where
|
||||||
|
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 5
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2);
|
||||||
|
a1
|
||||||
|
1 - 03
|
||||||
|
|
||||||
|
explain
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2 where b1 = '7 - 02');
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where
|
||||||
|
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 5 Using where
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2 where b1 = '7 - 02');
|
||||||
|
a1
|
||||||
/* E.6 make_join_select detects impossible WHERE. *
|
/* E.6 make_join_select detects impossible WHERE. *
|
||||||
TODO
|
TODO
|
||||||
/* E.7 constant optimization detects "no matching row in const table". */
|
/* E.7 constant optimization detects "no matching row in const table". */
|
||||||
|
@ -2446,7 +2548,22 @@ a1
|
||||||
/* E.5 opt_sum_query detects no matching min/max row or substitutes MIN/MAX with a const. */
|
/* E.5 opt_sum_query detects no matching min/max row or substitutes MIN/MAX with a const. */
|
||||||
TODO this test produces wrong result due to missing logic to handle the case
|
TODO this test produces wrong result due to missing logic to handle the case
|
||||||
when JOIN::optimize detects an empty subquery result.
|
when JOIN::optimize detects an empty subquery result.
|
||||||
|
explain
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2);
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where
|
||||||
|
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2);
|
||||||
|
a1
|
||||||
|
1 - 03
|
||||||
|
|
||||||
|
explain
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2 where b1 = '7 - 02');
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where
|
||||||
|
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL No matching min/max row
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2 where b1 = '7 - 02');
|
||||||
|
a1
|
||||||
/* E.6 make_join_select detects impossible WHERE. *
|
/* E.6 make_join_select detects impossible WHERE. *
|
||||||
TODO
|
TODO
|
||||||
/* E.7 constant optimization detects "no matching row in const table". */
|
/* E.7 constant optimization detects "no matching row in const table". */
|
||||||
|
@ -2758,7 +2875,22 @@ a1
|
||||||
/* E.5 opt_sum_query detects no matching min/max row or substitutes MIN/MAX with a const. */
|
/* E.5 opt_sum_query detects no matching min/max row or substitutes MIN/MAX with a const. */
|
||||||
TODO this test produces wrong result due to missing logic to handle the case
|
TODO this test produces wrong result due to missing logic to handle the case
|
||||||
when JOIN::optimize detects an empty subquery result.
|
when JOIN::optimize detects an empty subquery result.
|
||||||
|
explain
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2);
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where
|
||||||
|
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2);
|
||||||
|
a1
|
||||||
|
1 - 03
|
||||||
|
|
||||||
|
explain
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2 where b1 = '7 - 02');
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where
|
||||||
|
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL No matching min/max row
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2 where b1 = '7 - 02');
|
||||||
|
a1
|
||||||
/* E.6 make_join_select detects impossible WHERE. *
|
/* E.6 make_join_select detects impossible WHERE. *
|
||||||
TODO
|
TODO
|
||||||
/* E.7 constant optimization detects "no matching row in const table". */
|
/* E.7 constant optimization detects "no matching row in const table". */
|
||||||
|
@ -3032,7 +3164,21 @@ a1
|
||||||
/* E.5 opt_sum_query detects no matching min/max row or substitutes MIN/MAX with a const. */
|
/* E.5 opt_sum_query detects no matching min/max row or substitutes MIN/MAX with a const. */
|
||||||
TODO this test produces wrong result due to missing logic to handle the case
|
TODO this test produces wrong result due to missing logic to handle the case
|
||||||
when JOIN::optimize detects an empty subquery result.
|
when JOIN::optimize detects an empty subquery result.
|
||||||
|
explain
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2);
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 index NULL it1i1 9 NULL 3 Using where; Using index
|
||||||
|
2 SUBQUERY t2 ALL NULL NULL NULL NULL 5
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2);
|
||||||
|
a1
|
||||||
|
|
||||||
|
explain
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2 where b1 = '7 - 02');
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 index NULL it1i1 9 NULL 3 Using where; Using index
|
||||||
|
2 SUBQUERY t2 ALL NULL NULL NULL NULL 5 Using where
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2 where b1 = '7 - 02');
|
||||||
|
a1
|
||||||
/* E.6 make_join_select detects impossible WHERE. *
|
/* E.6 make_join_select detects impossible WHERE. *
|
||||||
TODO
|
TODO
|
||||||
/* E.7 constant optimization detects "no matching row in const table". */
|
/* E.7 constant optimization detects "no matching row in const table". */
|
||||||
|
@ -3299,7 +3445,21 @@ a1
|
||||||
/* E.5 opt_sum_query detects no matching min/max row or substitutes MIN/MAX with a const. */
|
/* E.5 opt_sum_query detects no matching min/max row or substitutes MIN/MAX with a const. */
|
||||||
TODO this test produces wrong result due to missing logic to handle the case
|
TODO this test produces wrong result due to missing logic to handle the case
|
||||||
when JOIN::optimize detects an empty subquery result.
|
when JOIN::optimize detects an empty subquery result.
|
||||||
|
explain
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2);
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 index NULL it1i1 9 NULL 3 Using where; Using index
|
||||||
|
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2);
|
||||||
|
a1
|
||||||
|
|
||||||
|
explain
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2 where b1 = '7 - 02');
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 index NULL it1i1 9 NULL 3 Using where; Using index
|
||||||
|
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL No matching min/max row
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2 where b1 = '7 - 02');
|
||||||
|
a1
|
||||||
/* E.6 make_join_select detects impossible WHERE. *
|
/* E.6 make_join_select detects impossible WHERE. *
|
||||||
TODO
|
TODO
|
||||||
/* E.7 constant optimization detects "no matching row in const table". */
|
/* E.7 constant optimization detects "no matching row in const table". */
|
||||||
|
@ -3566,7 +3726,21 @@ a1
|
||||||
/* E.5 opt_sum_query detects no matching min/max row or substitutes MIN/MAX with a const. */
|
/* E.5 opt_sum_query detects no matching min/max row or substitutes MIN/MAX with a const. */
|
||||||
TODO this test produces wrong result due to missing logic to handle the case
|
TODO this test produces wrong result due to missing logic to handle the case
|
||||||
when JOIN::optimize detects an empty subquery result.
|
when JOIN::optimize detects an empty subquery result.
|
||||||
|
explain
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2);
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 index NULL it1i1 8 NULL 3 Using where; Using index
|
||||||
|
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2);
|
||||||
|
a1
|
||||||
|
|
||||||
|
explain
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2 where b1 = '7 - 02');
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 index NULL it1i1 8 NULL 3 Using where; Using index
|
||||||
|
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL No matching min/max row
|
||||||
|
select a1 from t1 where a1 in (select max(b1) from t2 where b1 = '7 - 02');
|
||||||
|
a1
|
||||||
/* E.6 make_join_select detects impossible WHERE. *
|
/* E.6 make_join_select detects impossible WHERE. *
|
||||||
TODO
|
TODO
|
||||||
/* E.7 constant optimization detects "no matching row in const table". */
|
/* E.7 constant optimization detects "no matching row in const table". */
|
||||||
|
|
|
@ -36,7 +36,7 @@ Item_subselect::Item_subselect():
|
||||||
Item_result_field(), value_assigned(0), thd(0), substitution(0),
|
Item_result_field(), value_assigned(0), thd(0), substitution(0),
|
||||||
engine(0), old_engine(0), used_tables_cache(0), have_to_be_excluded(0),
|
engine(0), old_engine(0), used_tables_cache(0), have_to_be_excluded(0),
|
||||||
const_item_cache(1),
|
const_item_cache(1),
|
||||||
inside_first_fix_fields(0), done_first_fix_fields(FALSE),
|
inside_first_fix_fields(0), done_first_fix_fields(FALSE), forced_const(FALSE),
|
||||||
eliminated(FALSE),
|
eliminated(FALSE),
|
||||||
engine_changed(0), changed(0), is_correlated(FALSE)
|
engine_changed(0), changed(0), is_correlated(FALSE)
|
||||||
{
|
{
|
||||||
|
@ -121,6 +121,7 @@ void Item_subselect::cleanup()
|
||||||
depends_on.empty();
|
depends_on.empty();
|
||||||
reset();
|
reset();
|
||||||
value_assigned= 0;
|
value_assigned= 0;
|
||||||
|
forced_const= FALSE;
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,7 +159,6 @@ void Item_in_subselect::cleanup()
|
||||||
left_expr_cache= NULL;
|
left_expr_cache= NULL;
|
||||||
}
|
}
|
||||||
first_execution= TRUE;
|
first_execution= TRUE;
|
||||||
is_constant= FALSE;
|
|
||||||
if (in_strategy & SUBS_MATERIALIZATION)
|
if (in_strategy & SUBS_MATERIALIZATION)
|
||||||
in_strategy= 0;
|
in_strategy= 0;
|
||||||
pushed_cond_guards= NULL;
|
pushed_cond_guards= NULL;
|
||||||
|
@ -682,12 +682,15 @@ Item *Item_subselect::get_tmp_table_item(THD *thd_arg)
|
||||||
|
|
||||||
void Item_subselect::update_used_tables()
|
void Item_subselect::update_used_tables()
|
||||||
{
|
{
|
||||||
recalc_used_tables(parent_select, FALSE);
|
if (!forced_const)
|
||||||
if (!engine->uncacheable())
|
|
||||||
{
|
{
|
||||||
// did all used tables become static?
|
recalc_used_tables(parent_select, FALSE);
|
||||||
if (!(used_tables_cache & ~engine->upper_select_const_tables()))
|
if (!engine->uncacheable())
|
||||||
const_item_cache= 1;
|
{
|
||||||
|
// did all used tables become static?
|
||||||
|
if (!(used_tables_cache & ~engine->upper_select_const_tables()))
|
||||||
|
const_item_cache= 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -753,7 +756,7 @@ Item_maxmin_subselect::Item_maxmin_subselect(THD *thd_param,
|
||||||
of Items belonged to subquery, which will be not repeated
|
of Items belonged to subquery, which will be not repeated
|
||||||
*/
|
*/
|
||||||
used_tables_cache= parent->get_used_tables_cache();
|
used_tables_cache= parent->get_used_tables_cache();
|
||||||
const_item_cache= parent->get_const_item_cache();
|
const_item_cache= parent->const_item();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
this subquery always creates during preparation, so we can assign
|
this subquery always creates during preparation, so we can assign
|
||||||
|
@ -791,8 +794,7 @@ void Item_maxmin_subselect::print(String *str, enum_query_type query_type)
|
||||||
|
|
||||||
void Item_singlerow_subselect::reset()
|
void Item_singlerow_subselect::reset()
|
||||||
{
|
{
|
||||||
eliminated= FALSE;
|
Item_subselect::reset();
|
||||||
null_value= 1;
|
|
||||||
if (value)
|
if (value)
|
||||||
value->null_value= 1;
|
value->null_value= 1;
|
||||||
}
|
}
|
||||||
|
@ -1082,8 +1084,7 @@ bool Item_in_subselect::test_limit(st_select_lex_unit *unit_arg)
|
||||||
Item_in_subselect::Item_in_subselect(Item * left_exp,
|
Item_in_subselect::Item_in_subselect(Item * left_exp,
|
||||||
st_select_lex *select_lex):
|
st_select_lex *select_lex):
|
||||||
Item_exists_subselect(), left_expr_cache(0), first_execution(TRUE),
|
Item_exists_subselect(), left_expr_cache(0), first_execution(TRUE),
|
||||||
is_constant(FALSE), optimizer(0), pushed_cond_guards(NULL),
|
optimizer(0), pushed_cond_guards(NULL), in_strategy(0), upper_item(0)
|
||||||
in_strategy(0), upper_item(0)
|
|
||||||
{
|
{
|
||||||
DBUG_ENTER("Item_in_subselect::Item_in_subselect");
|
DBUG_ENTER("Item_in_subselect::Item_in_subselect");
|
||||||
left_expr= left_exp;
|
left_expr= left_exp;
|
||||||
|
@ -1313,7 +1314,7 @@ bool Item_in_subselect::val_bool()
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
null_value= 0;
|
null_value= 0;
|
||||||
if (is_constant)
|
if (forced_const)
|
||||||
return value;
|
return value;
|
||||||
if (exec())
|
if (exec())
|
||||||
{
|
{
|
||||||
|
@ -4147,11 +4148,10 @@ int subselect_hash_sj_engine::exec()
|
||||||
tmp_table->file->info(HA_STATUS_VARIABLE);
|
tmp_table->file->info(HA_STATUS_VARIABLE);
|
||||||
if (!tmp_table->file->stats.records)
|
if (!tmp_table->file->stats.records)
|
||||||
{
|
{
|
||||||
item_in->value= FALSE;
|
|
||||||
/* The value of IN will not change during this execution. */
|
/* The value of IN will not change during this execution. */
|
||||||
item_in->is_constant= TRUE;
|
item_in->reset();
|
||||||
|
item_in->make_const();
|
||||||
item_in->set_first_execution();
|
item_in->set_first_execution();
|
||||||
/* TIMOUR: check if we need this: item_in->null_value= FALSE; */
|
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,13 @@ protected:
|
||||||
|
|
||||||
bool inside_first_fix_fields;
|
bool inside_first_fix_fields;
|
||||||
bool done_first_fix_fields;
|
bool done_first_fix_fields;
|
||||||
|
/*
|
||||||
|
Set to TRUE if at optimization or execution time we determine that this
|
||||||
|
item's value is a constant. We need this member because it is not possible
|
||||||
|
to substitute 'this' with a constant item.
|
||||||
|
*/
|
||||||
|
bool forced_const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/* A reference from inside subquery predicate to somewhere outside of it */
|
/* A reference from inside subquery predicate to somewhere outside of it */
|
||||||
class Ref_to_outside : public Sql_alloc
|
class Ref_to_outside : public Sql_alloc
|
||||||
|
@ -154,12 +161,21 @@ public:
|
||||||
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
|
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
|
||||||
void recalc_used_tables(st_select_lex *new_parent, bool after_pullout);
|
void recalc_used_tables(st_select_lex *new_parent, bool after_pullout);
|
||||||
virtual bool exec();
|
virtual bool exec();
|
||||||
|
/*
|
||||||
|
If subquery optimization or execution determines that the subquery has
|
||||||
|
an empty result, mark the subquery predicate as a constant value.
|
||||||
|
*/
|
||||||
|
void make_const()
|
||||||
|
{
|
||||||
|
used_tables_cache= 0;
|
||||||
|
const_item_cache= 0;
|
||||||
|
forced_const= TRUE;
|
||||||
|
}
|
||||||
virtual void fix_length_and_dec();
|
virtual void fix_length_and_dec();
|
||||||
table_map used_tables() const;
|
table_map used_tables() const;
|
||||||
table_map not_null_tables() const { return 0; }
|
table_map not_null_tables() const { return 0; }
|
||||||
bool const_item() const;
|
bool const_item() const;
|
||||||
inline table_map get_used_tables_cache() { return used_tables_cache; }
|
inline table_map get_used_tables_cache() { return used_tables_cache; }
|
||||||
inline bool get_const_item_cache() { return const_item_cache; }
|
|
||||||
Item *get_tmp_table_item(THD *thd);
|
Item *get_tmp_table_item(THD *thd);
|
||||||
void update_used_tables();
|
void update_used_tables();
|
||||||
virtual void print(String *str, enum_query_type query_type);
|
virtual void print(String *str, enum_query_type query_type);
|
||||||
|
@ -353,12 +369,6 @@ protected:
|
||||||
*/
|
*/
|
||||||
List<Cached_item> *left_expr_cache;
|
List<Cached_item> *left_expr_cache;
|
||||||
bool first_execution;
|
bool first_execution;
|
||||||
/*
|
|
||||||
Set to TRUE if at query execution time we determine that this item's
|
|
||||||
value is a constant during this execution. We need this member because
|
|
||||||
it is not possible to substitute 'this' with a constant item.
|
|
||||||
*/
|
|
||||||
bool is_constant;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
expr & optimizer used in subselect rewriting to store Item for
|
expr & optimizer used in subselect rewriting to store Item for
|
||||||
|
@ -435,7 +445,7 @@ public:
|
||||||
Item_in_subselect(Item * left_expr, st_select_lex *select_lex);
|
Item_in_subselect(Item * left_expr, st_select_lex *select_lex);
|
||||||
Item_in_subselect()
|
Item_in_subselect()
|
||||||
:Item_exists_subselect(), left_expr_cache(0), first_execution(TRUE),
|
:Item_exists_subselect(), left_expr_cache(0), first_execution(TRUE),
|
||||||
is_constant(FALSE), optimizer(0), abort_on_null(0),
|
optimizer(0), abort_on_null(0),
|
||||||
pushed_cond_guards(NULL), func(NULL), in_strategy(0),
|
pushed_cond_guards(NULL), func(NULL), in_strategy(0),
|
||||||
upper_item(0)
|
upper_item(0)
|
||||||
{}
|
{}
|
||||||
|
|
|
@ -3823,3 +3823,65 @@ bool JOIN::choose_subquery_plan(table_map join_tables)
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Choose a query plan for a table-less subquery.
|
||||||
|
|
||||||
|
@notes
|
||||||
|
|
||||||
|
@retval FALSE success.
|
||||||
|
@retval TRUE error occurred.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool JOIN::choose_tableless_subquery_plan()
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(!tables_list || !tables);
|
||||||
|
if (select_lex->master_unit()->item)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(select_lex->master_unit()->item->type() ==
|
||||||
|
Item::SUBSELECT_ITEM);
|
||||||
|
Item_subselect *subs_predicate= select_lex->master_unit()->item;
|
||||||
|
|
||||||
|
/*
|
||||||
|
If the optimizer determined that his query has an empty result,
|
||||||
|
in most cases the subquery predicate is a known constant value -
|
||||||
|
either FALSE or NULL. The implementation of Item_subselect::reset()
|
||||||
|
determines which one.
|
||||||
|
*/
|
||||||
|
if (zero_result_cause)
|
||||||
|
{
|
||||||
|
if (!implicit_grouping)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Both group by queries and non-group by queries without aggregate
|
||||||
|
functions produce empty subquery result.
|
||||||
|
*/
|
||||||
|
subs_predicate->reset();
|
||||||
|
subs_predicate->make_const();
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO:
|
||||||
|
A further optimization is possible when a non-group query with
|
||||||
|
MIN/MAX/COUNT is optimized by opt_sum_query. Then, if there are
|
||||||
|
only MIN/MAX functions over an empty result set, the subquery
|
||||||
|
result is a NULL value/row, thus the value of subs_predicate is
|
||||||
|
NULL.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subs_predicate->is_in_predicate())
|
||||||
|
{
|
||||||
|
Item_in_subselect *in_subs;
|
||||||
|
in_subs= (Item_in_subselect*) subs_predicate;
|
||||||
|
in_subs->in_strategy= SUBS_IN_TO_EXISTS;
|
||||||
|
if (in_subs->create_in_to_exists_cond(this) ||
|
||||||
|
in_subs->inject_in_to_exists_cond(this))
|
||||||
|
return TRUE;
|
||||||
|
tmp_having= having;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -829,6 +829,7 @@ JOIN::optimize()
|
||||||
"Impossible HAVING" : "Impossible WHERE";
|
"Impossible HAVING" : "Impossible WHERE";
|
||||||
tables= 0;
|
tables= 0;
|
||||||
error= 0;
|
error= 0;
|
||||||
|
choose_tableless_subquery_plan();
|
||||||
goto setup_subq_exit;
|
goto setup_subq_exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -873,12 +874,13 @@ JOIN::optimize()
|
||||||
*/
|
*/
|
||||||
if ((res=opt_sum_query(select_lex->leaf_tables, all_fields, conds)))
|
if ((res=opt_sum_query(select_lex->leaf_tables, all_fields, conds)))
|
||||||
{
|
{
|
||||||
if (res == HA_ERR_KEY_NOT_FOUND)
|
if (res == HA_ERR_KEY_NOT_FOUND || res < 0)
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info",("No matching min/max row"));
|
DBUG_PRINT("info",("No matching min/max row"));
|
||||||
zero_result_cause= "No matching min/max row";
|
zero_result_cause= "No matching min/max row";
|
||||||
tables= 0;
|
tables= 0;
|
||||||
error=0;
|
error=0;
|
||||||
|
choose_tableless_subquery_plan();
|
||||||
goto setup_subq_exit;
|
goto setup_subq_exit;
|
||||||
}
|
}
|
||||||
if (res > 1)
|
if (res > 1)
|
||||||
|
@ -887,14 +889,7 @@ JOIN::optimize()
|
||||||
DBUG_PRINT("error",("Error from opt_sum_query"));
|
DBUG_PRINT("error",("Error from opt_sum_query"));
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
if (res < 0)
|
|
||||||
{
|
|
||||||
DBUG_PRINT("info",("No matching min/max row"));
|
|
||||||
zero_result_cause= "No matching min/max row";
|
|
||||||
tables= 0;
|
|
||||||
error=0;
|
|
||||||
goto setup_subq_exit;
|
|
||||||
}
|
|
||||||
DBUG_PRINT("info",("Select tables optimized away"));
|
DBUG_PRINT("info",("Select tables optimized away"));
|
||||||
zero_result_cause= "Select tables optimized away";
|
zero_result_cause= "Select tables optimized away";
|
||||||
tables_list= 0; // All tables resolved
|
tables_list= 0; // All tables resolved
|
||||||
|
@ -919,40 +914,14 @@ JOIN::optimize()
|
||||||
QT_ORDINARY););
|
QT_ORDINARY););
|
||||||
conds= table_independent_conds;
|
conds= table_independent_conds;
|
||||||
}
|
}
|
||||||
goto setup_subq_exit;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!tables_list)
|
if (!tables_list)
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info",("No tables"));
|
DBUG_PRINT("info",("No tables"));
|
||||||
error= 0;
|
error= 0;
|
||||||
if (optimize_unflattened_subqueries())
|
choose_tableless_subquery_plan();
|
||||||
DBUG_RETURN(1);
|
goto setup_subq_exit;
|
||||||
/*
|
|
||||||
TIMOUR: TODO: consider do we need to optimize here at all and refactor
|
|
||||||
this block and JOIN::choose_subquery_plan.
|
|
||||||
|
|
||||||
if (choose_subquery_plan())
|
|
||||||
DBUG_RETURN(1);
|
|
||||||
*/
|
|
||||||
Item_in_subselect *in_subs;
|
|
||||||
if (select_lex->master_unit()->item &&
|
|
||||||
select_lex->master_unit()->item->is_in_predicate())
|
|
||||||
{
|
|
||||||
in_subs= (Item_in_subselect*) select_lex->master_unit()->item;
|
|
||||||
if (in_subs->in_strategy & SUBS_MATERIALIZATION &&
|
|
||||||
in_subs->setup_mat_engine())
|
|
||||||
in_subs->in_strategy= SUBS_IN_TO_EXISTS;
|
|
||||||
if (in_subs->in_strategy & SUBS_IN_TO_EXISTS)
|
|
||||||
{
|
|
||||||
if (in_subs->create_in_to_exists_cond(this))
|
|
||||||
DBUG_RETURN(1);
|
|
||||||
if (in_subs->inject_in_to_exists_cond(this))
|
|
||||||
DBUG_RETURN(1);
|
|
||||||
tmp_having= having;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DBUG_RETURN(0);
|
|
||||||
}
|
}
|
||||||
error= -1; // Error is sent to client
|
error= -1; // Error is sent to client
|
||||||
sort_by_table= get_sort_by_table(order, group_list, select_lex->leaf_tables);
|
sort_by_table= get_sort_by_table(order, group_list, select_lex->leaf_tables);
|
||||||
|
|
|
@ -1383,6 +1383,8 @@ protected:
|
||||||
void restore_query_plan(DYNAMIC_ARRAY *save_keyuse, POSITION *save_positions,
|
void restore_query_plan(DYNAMIC_ARRAY *save_keyuse, POSITION *save_positions,
|
||||||
KEYUSE **save_join_tab_keyuse,
|
KEYUSE **save_join_tab_keyuse,
|
||||||
key_map *save_join_tab_checked_keys);
|
key_map *save_join_tab_checked_keys);
|
||||||
|
/* Choose a subquery plan for a table-less subquery. */
|
||||||
|
bool choose_tableless_subquery_plan();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
JOIN_TAB *join_tab,**best_ref;
|
JOIN_TAB *join_tab,**best_ref;
|
||||||
|
|
Loading…
Add table
Reference in a new issue