Commit 30764334 authored by unknown's avatar unknown

fixed ALL/ANY optimisation with union (BUG#1668)

code cleanup


mysql-test/r/subselect.result:
  test for BUG#1668
mysql-test/t/subselect.test:
  test for BUG#1668
sql/item_subselect.cc:
  removed unused class field
  fixed min_max subquery used_tables()/const()
  fixed ALL/ANY optimisation for unions
sql/item_subselect.h:
  removed unused class field
  fixed min_max subquery used_tables()/const()
sql/sql_union.cc:
  fixed result object assignment
parent e559f183
...@@ -1489,3 +1489,17 @@ set sort_buffer_size = (select s1 from t1); ...@@ -1489,3 +1489,17 @@ set sort_buffer_size = (select s1 from t1);
ERROR 21000: Subquery returns more than 1 row ERROR 21000: Subquery returns more than 1 row
do (select * from t1); do (select * from t1);
drop table t1; drop table t1;
create table t1 (s1 char);
insert into t1 values ('e');
select * from t1 where 'f' > any (select s1 from t1);
s1
e
select * from t1 where 'f' > any (select s1 from t1 union select s1 from t1);
s1
e
explain select * from t1 where 'f' > any (select s1 from t1 union select s1 from t1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 system NULL NULL NULL NULL 1
2 SUBQUERY t1 system NULL NULL NULL NULL 1
3 UNION t1 system NULL NULL NULL NULL 1
drop table t1;
...@@ -1010,3 +1010,13 @@ insert into t1 values (2); ...@@ -1010,3 +1010,13 @@ insert into t1 values (2);
set sort_buffer_size = (select s1 from t1); set sort_buffer_size = (select s1 from t1);
do (select * from t1); do (select * from t1);
drop table t1; drop table t1;
#
# optimized ALL/ANY with union
#
create table t1 (s1 char);
insert into t1 values ('e');
select * from t1 where 'f' > any (select s1 from t1);
select * from t1 where 'f' > any (select s1 from t1 union select s1 from t1);
explain select * from t1 where 'f' > any (select s1 from t1 union select s1 from t1);
drop table t1;
...@@ -35,7 +35,7 @@ inline Item * and_items(Item* cond, Item *item) ...@@ -35,7 +35,7 @@ inline Item * and_items(Item* cond, Item *item)
} }
Item_subselect::Item_subselect(): Item_subselect::Item_subselect():
Item_result_field(), engine_owner(1), value_assigned(0), substitution(0), Item_result_field(), value_assigned(0), substitution(0),
engine(0), used_tables_cache(0), have_to_be_excluded(0), engine(0), used_tables_cache(0), have_to_be_excluded(0),
const_item_cache(1), engine_changed(0) const_item_cache(1), engine_changed(0)
{ {
...@@ -66,7 +66,6 @@ void Item_subselect::init(st_select_lex *select_lex, ...@@ -66,7 +66,6 @@ void Item_subselect::init(st_select_lex *select_lex,
Item_subselect::~Item_subselect() Item_subselect::~Item_subselect()
{ {
if (engine_owner)
delete engine; delete engine;
} }
...@@ -183,7 +182,8 @@ Item_singlerow_subselect::Item_singlerow_subselect(st_select_lex *select_lex) ...@@ -183,7 +182,8 @@ Item_singlerow_subselect::Item_singlerow_subselect(st_select_lex *select_lex)
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
Item_maxmin_subselect::Item_maxmin_subselect(st_select_lex *select_lex, Item_maxmin_subselect::Item_maxmin_subselect(Item_subselect *parent,
st_select_lex *select_lex,
bool max) bool max)
:Item_singlerow_subselect() :Item_singlerow_subselect()
{ {
...@@ -192,6 +192,14 @@ Item_maxmin_subselect::Item_maxmin_subselect(st_select_lex *select_lex, ...@@ -192,6 +192,14 @@ Item_maxmin_subselect::Item_maxmin_subselect(st_select_lex *select_lex,
max_columns= 1; max_columns= 1;
maybe_null= 1; maybe_null= 1;
max_columns= 1; max_columns= 1;
/*
Following information was collected during performing fix_fields()
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();
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -527,9 +535,16 @@ Item_in_subselect::single_value_transformer(JOIN *join, ...@@ -527,9 +535,16 @@ Item_in_subselect::single_value_transformer(JOIN *join,
func == &Item_bool_func2::ge_creator || func == &Item_bool_func2::ge_creator ||
func == &Item_bool_func2::le_creator)) func == &Item_bool_func2::le_creator))
{ {
if (substitution)
{
// It is second (third, ...) SELECT of UNION => All is done
DBUG_RETURN(RES_OK);
}
Item *subs; Item *subs;
if (!select_lex->group_list.elements && if (!select_lex->group_list.elements &&
!select_lex->with_sum_func) !select_lex->with_sum_func &&
!(select_lex->next_select()))
{ {
Item *item; Item *item;
subs_type type= substype(); subs_type type= substype();
...@@ -565,7 +580,7 @@ Item_in_subselect::single_value_transformer(JOIN *join, ...@@ -565,7 +580,7 @@ Item_in_subselect::single_value_transformer(JOIN *join,
// remove LIMIT placed by ALL/ANY subquery // remove LIMIT placed by ALL/ANY subquery
select_lex->master_unit()->global_parameters->select_limit= select_lex->master_unit()->global_parameters->select_limit=
HA_POS_ERROR; HA_POS_ERROR;
subs= new Item_maxmin_subselect(select_lex, subs= new Item_maxmin_subselect(this, select_lex,
(func == &Item_bool_func2::le_creator || (func == &Item_bool_func2::le_creator ||
func == &Item_bool_func2::lt_creator)); func == &Item_bool_func2::lt_creator));
} }
......
...@@ -33,7 +33,6 @@ typedef Item_bool_func2* (*compare_func_creator)(Item*, Item*); ...@@ -33,7 +33,6 @@ typedef Item_bool_func2* (*compare_func_creator)(Item*, Item*);
class Item_subselect :public Item_result_field class Item_subselect :public Item_result_field
{ {
my_bool engine_owner; /* Is this item owner of engine */
my_bool value_assigned; /* value already assigned to subselect */ my_bool value_assigned; /* value already assigned to subselect */
protected: protected:
/* thread handler, will be assigned in fix_fields only */ /* thread handler, will be assigned in fix_fields only */
...@@ -90,6 +89,8 @@ class Item_subselect :public Item_result_field ...@@ -90,6 +89,8 @@ class Item_subselect :public Item_result_field
virtual void fix_length_and_dec(); virtual void fix_length_and_dec();
table_map used_tables() const; table_map used_tables() const;
bool const_item() const; 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; }
void update_used_tables(); void update_used_tables();
void print(String *str) void print(String *str)
{ {
...@@ -144,10 +145,11 @@ class Item_singlerow_subselect :public Item_subselect ...@@ -144,10 +145,11 @@ class Item_singlerow_subselect :public Item_subselect
}; };
/* used in static ALL/ANY optimisation */ /* used in static ALL/ANY optimisation */
class Item_maxmin_subselect: public Item_singlerow_subselect class Item_maxmin_subselect :public Item_singlerow_subselect
{ {
public: public:
Item_maxmin_subselect(st_select_lex *select_lex, bool max); Item_maxmin_subselect(Item_subselect *parent,
st_select_lex *select_lex, bool max);
}; };
/* exists subselect */ /* exists subselect */
......
...@@ -119,13 +119,18 @@ int st_select_lex_unit::prepare(THD *thd, select_result *sel_result, ...@@ -119,13 +119,18 @@ int st_select_lex_unit::prepare(THD *thd, select_result *sel_result,
SELECT_LEX *select_cursor,*sl; SELECT_LEX *select_cursor,*sl;
DBUG_ENTER("st_select_lex_unit::prepare"); DBUG_ENTER("st_select_lex_unit::prepare");
/*
result object should be reassigned even if preparing already done for
max/min subquery (ALL/ANY optimization)
*/
result= sel_result;
if (prepared) if (prepared)
DBUG_RETURN(0); DBUG_RETURN(0);
prepared= 1; prepared= 1;
res= 0; res= 0;
found_rows_for_union= first_select_in_union()->options & OPTION_FOUND_ROWS; found_rows_for_union= first_select_in_union()->options & OPTION_FOUND_ROWS;
TMP_TABLE_PARAM tmp_table_param; TMP_TABLE_PARAM tmp_table_param;
result= sel_result;
t_and_f= tables_and_fields_initied; t_and_f= tables_and_fields_initied;
bzero((char *)&tmp_table_param,sizeof(TMP_TABLE_PARAM)); bzero((char *)&tmp_table_param,sizeof(TMP_TABLE_PARAM));
......
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