mirror of
https://github.com/MariaDB/server.git
synced 2025-01-25 08:14:18 +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 TODO this test produces wrong result due to missing logic to handle the case
|
||||
-- echo when JOIN::optimize detects an empty subquery result.
|
||||
#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);
|
||||
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);
|
||||
-- echo
|
||||
#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');
|
||||
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');
|
||||
|
||||
-- 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. */
|
||||
TODO this test produces wrong result due to missing logic to handle the case
|
||||
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. *
|
||||
TODO
|
||||
/* 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. */
|
||||
TODO this test produces wrong result due to missing logic to handle the case
|
||||
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. *
|
||||
TODO
|
||||
/* 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. */
|
||||
TODO this test produces wrong result due to missing logic to handle the case
|
||||
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. *
|
||||
TODO
|
||||
/* 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. */
|
||||
TODO this test produces wrong result due to missing logic to handle the case
|
||||
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. *
|
||||
TODO
|
||||
/* 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. */
|
||||
TODO this test produces wrong result due to missing logic to handle the case
|
||||
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. *
|
||||
TODO
|
||||
/* 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. */
|
||||
TODO this test produces wrong result due to missing logic to handle the case
|
||||
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. *
|
||||
TODO
|
||||
/* 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. */
|
||||
TODO this test produces wrong result due to missing logic to handle the case
|
||||
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. *
|
||||
TODO
|
||||
/* 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. */
|
||||
TODO this test produces wrong result due to missing logic to handle the case
|
||||
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. *
|
||||
TODO
|
||||
/* 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. */
|
||||
TODO this test produces wrong result due to missing logic to handle the case
|
||||
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. *
|
||||
TODO
|
||||
/* 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. */
|
||||
TODO this test produces wrong result due to missing logic to handle the case
|
||||
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. *
|
||||
TODO
|
||||
/* 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. */
|
||||
TODO this test produces wrong result due to missing logic to handle the case
|
||||
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. *
|
||||
TODO
|
||||
/* 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. */
|
||||
TODO this test produces wrong result due to missing logic to handle the case
|
||||
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. *
|
||||
TODO
|
||||
/* 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),
|
||||
engine(0), old_engine(0), used_tables_cache(0), have_to_be_excluded(0),
|
||||
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),
|
||||
engine_changed(0), changed(0), is_correlated(FALSE)
|
||||
{
|
||||
|
@ -121,6 +121,7 @@ void Item_subselect::cleanup()
|
|||
depends_on.empty();
|
||||
reset();
|
||||
value_assigned= 0;
|
||||
forced_const= FALSE;
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
@ -158,7 +159,6 @@ void Item_in_subselect::cleanup()
|
|||
left_expr_cache= NULL;
|
||||
}
|
||||
first_execution= TRUE;
|
||||
is_constant= FALSE;
|
||||
if (in_strategy & SUBS_MATERIALIZATION)
|
||||
in_strategy= 0;
|
||||
pushed_cond_guards= NULL;
|
||||
|
@ -682,12 +682,15 @@ Item *Item_subselect::get_tmp_table_item(THD *thd_arg)
|
|||
|
||||
void Item_subselect::update_used_tables()
|
||||
{
|
||||
recalc_used_tables(parent_select, FALSE);
|
||||
if (!engine->uncacheable())
|
||||
if (!forced_const)
|
||||
{
|
||||
// did all used tables become static?
|
||||
if (!(used_tables_cache & ~engine->upper_select_const_tables()))
|
||||
const_item_cache= 1;
|
||||
recalc_used_tables(parent_select, FALSE);
|
||||
if (!engine->uncacheable())
|
||||
{
|
||||
// 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
|
||||
*/
|
||||
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
|
||||
|
@ -791,8 +794,7 @@ void Item_maxmin_subselect::print(String *str, enum_query_type query_type)
|
|||
|
||||
void Item_singlerow_subselect::reset()
|
||||
{
|
||||
eliminated= FALSE;
|
||||
null_value= 1;
|
||||
Item_subselect::reset();
|
||||
if (value)
|
||||
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,
|
||||
st_select_lex *select_lex):
|
||||
Item_exists_subselect(), left_expr_cache(0), first_execution(TRUE),
|
||||
is_constant(FALSE), optimizer(0), pushed_cond_guards(NULL),
|
||||
in_strategy(0), upper_item(0)
|
||||
optimizer(0), pushed_cond_guards(NULL), in_strategy(0), upper_item(0)
|
||||
{
|
||||
DBUG_ENTER("Item_in_subselect::Item_in_subselect");
|
||||
left_expr= left_exp;
|
||||
|
@ -1313,7 +1314,7 @@ bool Item_in_subselect::val_bool()
|
|||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
null_value= 0;
|
||||
if (is_constant)
|
||||
if (forced_const)
|
||||
return value;
|
||||
if (exec())
|
||||
{
|
||||
|
@ -4147,11 +4148,10 @@ int subselect_hash_sj_engine::exec()
|
|||
tmp_table->file->info(HA_STATUS_VARIABLE);
|
||||
if (!tmp_table->file->stats.records)
|
||||
{
|
||||
item_in->value= FALSE;
|
||||
/* 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();
|
||||
/* TIMOUR: check if we need this: item_in->null_value= FALSE; */
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
|
||||
|
|
|
@ -70,6 +70,13 @@ protected:
|
|||
|
||||
bool inside_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:
|
||||
/* A reference from inside subquery predicate to somewhere outside of it */
|
||||
class Ref_to_outside : public Sql_alloc
|
||||
|
@ -154,12 +161,21 @@ public:
|
|||
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
|
||||
void recalc_used_tables(st_select_lex *new_parent, bool after_pullout);
|
||||
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();
|
||||
table_map used_tables() const;
|
||||
table_map not_null_tables() const { return 0; }
|
||||
bool const_item() const;
|
||||
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);
|
||||
void update_used_tables();
|
||||
virtual void print(String *str, enum_query_type query_type);
|
||||
|
@ -353,12 +369,6 @@ protected:
|
|||
*/
|
||||
List<Cached_item> *left_expr_cache;
|
||||
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
|
||||
|
@ -435,7 +445,7 @@ public:
|
|||
Item_in_subselect(Item * left_expr, st_select_lex *select_lex);
|
||||
Item_in_subselect()
|
||||
: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),
|
||||
upper_item(0)
|
||||
{}
|
||||
|
|
|
@ -3823,3 +3823,65 @@ bool JOIN::choose_subquery_plan(table_map join_tables)
|
|||
|
||||
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";
|
||||
tables= 0;
|
||||
error= 0;
|
||||
choose_tableless_subquery_plan();
|
||||
goto setup_subq_exit;
|
||||
}
|
||||
}
|
||||
|
@ -873,12 +874,13 @@ JOIN::optimize()
|
|||
*/
|
||||
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"));
|
||||
zero_result_cause= "No matching min/max row";
|
||||
tables= 0;
|
||||
error=0;
|
||||
choose_tableless_subquery_plan();
|
||||
goto setup_subq_exit;
|
||||
}
|
||||
if (res > 1)
|
||||
|
@ -887,14 +889,7 @@ JOIN::optimize()
|
|||
DBUG_PRINT("error",("Error from opt_sum_query"));
|
||||
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"));
|
||||
zero_result_cause= "Select tables optimized away";
|
||||
tables_list= 0; // All tables resolved
|
||||
|
@ -919,40 +914,14 @@ JOIN::optimize()
|
|||
QT_ORDINARY););
|
||||
conds= table_independent_conds;
|
||||
}
|
||||
goto setup_subq_exit;
|
||||
}
|
||||
}
|
||||
if (!tables_list)
|
||||
{
|
||||
DBUG_PRINT("info",("No tables"));
|
||||
error= 0;
|
||||
if (optimize_unflattened_subqueries())
|
||||
DBUG_RETURN(1);
|
||||
/*
|
||||
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);
|
||||
choose_tableless_subquery_plan();
|
||||
goto setup_subq_exit;
|
||||
}
|
||||
error= -1; // Error is sent to client
|
||||
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,
|
||||
KEYUSE **save_join_tab_keyuse,
|
||||
key_map *save_join_tab_checked_keys);
|
||||
/* Choose a subquery plan for a table-less subquery. */
|
||||
bool choose_tableless_subquery_plan();
|
||||
|
||||
public:
|
||||
JOIN_TAB *join_tab,**best_ref;
|
||||
|
|
Loading…
Add table
Reference in a new issue