Commit 1dd7cb52 authored by bell@sanja.is.com.ua's avatar bell@sanja.is.com.ua

support of subselect without FROM reducing (SCRUM)

fixed bug of calling setup_fields without correct lex->current_select pointer in mysql_derived
more correct creation of reference in Item_field::fix_field
parent 521ec316
select (select 2); select (select 2);
(select 2) (select 2)
2 2
explain select (select 2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1247 Select 2 was reduced during optimisation
SELECT (SELECT 1) UNION SELECT (SELECT 2); SELECT (SELECT 1) UNION SELECT (SELECT 2);
(SELECT 1) (SELECT 1)
1 1
2 2
explain SELECT (SELECT 1) UNION SELECT (SELECT 2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
3 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1247 Select 2 was reduced during optimisation
Note 1247 Select 4 was reduced during optimisation
SELECT (SELECT (SELECT 0 UNION SELECT 0)); SELECT (SELECT (SELECT 0 UNION SELECT 0));
(SELECT (SELECT 0 UNION SELECT 0)) (SELECT (SELECT 0 UNION SELECT 0))
0 0
explain SELECT (SELECT (SELECT 0 UNION SELECT 0));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
3 SUBSELECT NULL NULL NULL NULL NULL NULL NULL No tables used
4 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1247 Select 2 was reduced during optimisation
SELECT (SELECT 1 FROM (SELECT 1) as b HAVING a=1) as a; SELECT (SELECT 1 FROM (SELECT 1) as b HAVING a=1) as a;
Reference 'a' not supported (forward reference in item list) Reference 'a' not supported (forward reference in item list)
SELECT (SELECT 1 FROM (SELECT 1) as b HAVING b=1) as a,(SELECT 1 FROM (SELECT 1) as c HAVING a=1) as b; SELECT (SELECT 1 FROM (SELECT 1) as b HAVING b=1) as a,(SELECT 1 FROM (SELECT 1) as c HAVING a=1) as b;
...@@ -20,8 +39,9 @@ Reference 'a' not supported (forward reference in item list) ...@@ -20,8 +39,9 @@ Reference 'a' not supported (forward reference in item list)
EXPLAIN SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1; EXPLAIN SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1;
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 <derived2> system NULL NULL NULL NULL 1 1 PRIMARY <derived2> system NULL NULL NULL NULL 1
3 DEPENDENT SUBSELECT NULL NULL NULL NULL NULL NULL NULL No tables used
2 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used 2 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1247 Select 3 was reduced during optimisation
SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1; SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1;
1 1
1 1
...@@ -629,6 +649,7 @@ id select_type table type possible_keys key key_len ref rows Extra ...@@ -629,6 +649,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t ref id id 5 const 1 Using where; Using index 1 PRIMARY t ref id id 5 const 1 Using where; Using index
3 SUBSELECT NULL NULL NULL NULL NULL NULL NULL No tables used 3 SUBSELECT NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings: Warnings:
Note 1247 Select 3 was reduced during optimisation
Note 1247 Select 2 was reduced during optimisation Note 1247 Select 2 was reduced during optimisation
EXPLAIN SELECT * FROM t WHERE id IN (SELECT 1 UNION SELECT 3); EXPLAIN SELECT * FROM t WHERE id IN (SELECT 1 UNION SELECT 3);
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
...@@ -752,6 +773,16 @@ NULL ...@@ -752,6 +773,16 @@ NULL
select 10.5 > ANY (SELECT * from t); select 10.5 > ANY (SELECT * from t);
10.5 > ANY (SELECT * from t) 10.5 > ANY (SELECT * from t)
1 1
explain select (select a+1) from t;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t ALL NULL NULL NULL NULL 3
Warnings:
Note 1247 Select 2 was reduced during optimisation
select (select a+1) from t;
(select a+1)
2.5
NULL
4.5
drop table t; drop table t;
create table t (a float); create table t (a float);
select 10.5 IN (SELECT * from t LIMIT 1); select 10.5 IN (SELECT * from t LIMIT 1);
......
select (select 2); select (select 2);
explain select (select 2);
SELECT (SELECT 1) UNION SELECT (SELECT 2); SELECT (SELECT 1) UNION SELECT (SELECT 2);
explain SELECT (SELECT 1) UNION SELECT (SELECT 2);
SELECT (SELECT (SELECT 0 UNION SELECT 0)); SELECT (SELECT (SELECT 0 UNION SELECT 0));
explain SELECT (SELECT (SELECT 0 UNION SELECT 0));
-- error 1245 -- error 1245
SELECT (SELECT 1 FROM (SELECT 1) as b HAVING a=1) as a; SELECT (SELECT 1 FROM (SELECT 1) as b HAVING a=1) as a;
-- error 1245 -- error 1245
...@@ -424,6 +427,8 @@ select 1.5 > ALL (SELECT * from t); ...@@ -424,6 +427,8 @@ select 1.5 > ALL (SELECT * from t);
select 10.5 > ALL (SELECT * from t); select 10.5 > ALL (SELECT * from t);
select 1.5 > ANY (SELECT * from t); select 1.5 > ANY (SELECT * from t);
select 10.5 > ANY (SELECT * from t); select 10.5 > ANY (SELECT * from t);
explain select (select a+1) from t;
select (select a+1) from t;
drop table t; drop table t;
#LIMIT is not supported now #LIMIT is not supported now
...@@ -433,6 +438,7 @@ select 10.5 IN (SELECT * from t LIMIT 1); ...@@ -433,6 +438,7 @@ select 10.5 IN (SELECT * from t LIMIT 1);
-- error 1235 -- error 1235
select 10.5 IN (SELECT * from t LIMIT 1 UNION SELECT 1.5); select 10.5 IN (SELECT * from t LIMIT 1 UNION SELECT 1.5);
drop table t; drop table t;
create table t1 (a int, b int, c varchar(10)); create table t1 (a int, b int, c varchar(10));
create table t2 (a int); create table t2 (a int);
insert into t1 values (1,2,'a'),(2,3,'b'),(3,4,'c'); insert into t1 values (1,2,'a'),(2,3,'b'),(3,4,'c');
......
...@@ -546,8 +546,11 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ...@@ -546,8 +546,11 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{ {
if (!field) // If field is not checked if (!field) // If field is not checked
{ {
Field *tmp; TABLE_LIST *where= 0;
if ((tmp= find_field_in_tables(thd, this, tables, 0)) == not_found_field) Field *tmp= (Field *)not_found_field;
if (outer_resolving ||
(tmp= find_field_in_tables(thd, this, tables, &where, 0)) ==
not_found_field)
{ {
/* /*
We can't find table field in table list of current select, We can't find table field in table list of current select,
...@@ -565,12 +568,12 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ...@@ -565,12 +568,12 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
SELECT_LEX *cursel=(SELECT_LEX *) thd->lex.current_select; SELECT_LEX *cursel=(SELECT_LEX *) thd->lex.current_select;
if (cursel->master_unit()->first_select()->linkage != if (cursel->master_unit()->first_select()->linkage !=
DERIVED_TABLE_TYPE) DERIVED_TABLE_TYPE)
for (SELECT_LEX *sl=cursel->outer_select(); for (SELECT_LEX *sl=(outer_resolving?cursel:cursel->outer_select());
sl; sl;
sl= sl->outer_select()) sl= sl->outer_select())
{ {
if ((tmp= find_field_in_tables(thd, this, if ((tmp= find_field_in_tables(thd, this,
(last= sl)->get_table_list(), (last= sl)->get_table_list(), &where,
0)) != not_found_field) 0)) != not_found_field)
break; break;
if ((refer= find_item_in_list(this, sl->item_list, if ((refer= find_item_in_list(this, sl->item_list,
...@@ -588,7 +591,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ...@@ -588,7 +591,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
else if (tmp == not_found_field && refer == (Item **)not_found_item) else if (tmp == not_found_field && refer == (Item **)not_found_item)
{ {
// call to return error code // call to return error code
find_field_in_tables(thd, this, tables, 1); find_field_in_tables(thd, this, tables, &where, 1);
return -1; return -1;
} }
else if (refer != (Item **)not_found_item) else if (refer != (Item **)not_found_item)
...@@ -614,6 +617,17 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ...@@ -614,6 +617,17 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
found table as depended (of select where was found table) found table as depended (of select where was found table)
*/ */
thd->lex.current_select->mark_as_dependent(last); thd->lex.current_select->mark_as_dependent(last);
if (depended_from->having_fix_field)
{
Item_ref *rf;
*ref= rf= new Item_ref((where->db[0]?where->db:0),
(char *)where->alias,
(char *)field_name);
if (!rf)
return 1;
(rf)->outer_resolving= outer_resolving;
return rf->check_cols(1) || rf->fix_fields(thd, tables, ref);
}
} }
} }
else if (!tmp) else if (!tmp)
...@@ -629,14 +643,6 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ...@@ -629,14 +643,6 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
table->used_fields++; table->used_fields++;
table->used_keys&=field->part_of_key; table->used_keys&=field->part_of_key;
} }
if (depended_from != 0 && depended_from->having_fix_field)
{
*ref= new Item_ref((char *)db_name, (char *)table_name,
(char *)field_name);
if (!*ref)
return 1;
return (*ref)->check_cols(1) || (*ref)->fix_fields(thd, tables, ref);
}
fixed= 1; fixed= 1;
return 0; return 0;
} }
...@@ -1007,13 +1013,17 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) ...@@ -1007,13 +1013,17 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
{ {
if (!ref) if (!ref)
{ {
SELECT_LEX *sl= thd->lex.current_select->outer_select(); TABLE_LIST *where= 0;
SELECT_LEX *sl= (outer_resolving?
thd->lex.current_select->select_lex():
thd->lex.current_select->outer_select());
/* /*
Finding only in current select will be performed for selects that have Finding only in current select will be performed for selects that have
not outer one and for derived tables (which not support using outer not outer one and for derived tables (which not support using outer
fields for now) fields for now)
*/ */
if ((ref= find_item_in_list(this, if (outer_resolving ||
(ref= find_item_in_list(this,
*(thd->lex.current_select->get_item_list()), *(thd->lex.current_select->get_item_list()),
((sl && ((sl &&
thd->lex.current_select->master_unit()-> thd->lex.current_select->master_unit()->
...@@ -1041,7 +1051,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) ...@@ -1041,7 +1051,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
(Item **)not_found_item) (Item **)not_found_item)
break; break;
if ((tmp= find_field_in_tables(thd, this, if ((tmp= find_field_in_tables(thd, this,
sl->get_table_list(), sl->get_table_list(), &where,
0)) != not_found_field); 0)) != not_found_field);
if (sl->master_unit()->first_select()->linkage == if (sl->master_unit()->first_select()->linkage ==
DERIVED_TABLE_TYPE) DERIVED_TABLE_TYPE)
......
...@@ -96,6 +96,7 @@ class Item { ...@@ -96,6 +96,7 @@ class Item {
CHARSET_INFO *thd_charset() const; CHARSET_INFO *thd_charset() const;
CHARSET_INFO *charset() const { return str_value.charset(); }; CHARSET_INFO *charset() const { return str_value.charset(); };
void set_charset(CHARSET_INFO *cs) { str_value.set_charset(cs); } void set_charset(CHARSET_INFO *cs) { str_value.set_charset(cs); }
virtual void set_outer_resolving() {}
// Row emulation // Row emulation
virtual uint cols() { return 1; } virtual uint cols() { return 1; }
...@@ -117,12 +118,14 @@ class Item_ident :public Item ...@@ -117,12 +118,14 @@ class Item_ident :public Item
const char *table_name; const char *table_name;
const char *field_name; const char *field_name;
st_select_lex *depended_from; st_select_lex *depended_from;
bool outer_resolving; /* used for items from reduced subselect */
Item_ident(const char *db_name_par,const char *table_name_par, Item_ident(const char *db_name_par,const char *table_name_par,
const char *field_name_par) const char *field_name_par)
:db_name(db_name_par),table_name(table_name_par), :db_name(db_name_par), table_name(table_name_par),
field_name(field_name_par), depended_from(0) field_name(field_name_par), depended_from(0), outer_resolving(0)
{ name = (char*) field_name_par; } { name = (char*) field_name_par; }
const char *full_name() const; const char *full_name() const;
void set_outer_resolving() { outer_resolving= 1; }
}; };
......
...@@ -946,6 +946,13 @@ Item_func_case::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ...@@ -946,6 +946,13 @@ Item_func_case::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
return 0; return 0;
} }
void Item_func_case::set_outer_resolving()
{
first_expr->set_outer_resolving();
else_expr->set_outer_resolving();
Item_func::set_outer_resolving();
}
bool Item_func_case::check_loop(uint id) bool Item_func_case::check_loop(uint id)
{ {
DBUG_ENTER("Item_func_case::check_loop"); DBUG_ENTER("Item_func_case::check_loop");
...@@ -1523,6 +1530,15 @@ bool Item_cond::check_loop(uint id) ...@@ -1523,6 +1530,15 @@ bool Item_cond::check_loop(uint id)
DBUG_RETURN(0); DBUG_RETURN(0);
} }
void Item_cond::set_outer_resolving()
{
Item_func::set_outer_resolving();
List_iterator<Item> li(list);
Item *item;
while ((item= li++))
item->set_outer_resolving();
}
void Item_cond::split_sum_func(List<Item> &fields) void Item_cond::split_sum_func(List<Item> &fields)
{ {
List_iterator<Item> li(list); List_iterator<Item> li(list);
......
...@@ -277,6 +277,11 @@ class Item_func_interval :public Item_int_func ...@@ -277,6 +277,11 @@ class Item_func_interval :public Item_int_func
const char *func_name() const { return "interval"; } const char *func_name() const { return "interval"; }
void update_used_tables(); void update_used_tables();
bool check_loop(uint id); bool check_loop(uint id);
void set_outer_resolving()
{
item->set_outer_resolving();
Item_func::set_outer_resolving();
}
}; };
...@@ -359,6 +364,7 @@ class Item_func_case :public Item_func ...@@ -359,6 +364,7 @@ class Item_func_case :public Item_func
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref); bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
Item *find_item(String *str); Item *find_item(String *str);
bool check_loop(uint id); bool check_loop(uint id);
void set_outer_resolving();
}; };
...@@ -643,6 +649,11 @@ class Item_func_in :public Item_int_func ...@@ -643,6 +649,11 @@ class Item_func_in :public Item_int_func
DBUG_RETURN(item->check_loop(id)); DBUG_RETURN(item->check_loop(id));
} }
bool nulls_in_row(); bool nulls_in_row();
void set_outer_resolving()
{
item->set_outer_resolving();
Item_int_func::set_outer_resolving();
}
}; };
/* Functions used by where clause */ /* Functions used by where clause */
...@@ -784,6 +795,7 @@ class Item_cond :public Item_bool_func ...@@ -784,6 +795,7 @@ class Item_cond :public Item_bool_func
friend int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds); friend int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds);
bool check_loop(uint id); bool check_loop(uint id);
void top_level_item() { abort_on_null=1; } void top_level_item() { abort_on_null=1; }
void set_outer_resolving();
}; };
......
...@@ -146,6 +146,16 @@ bool Item_func::check_loop(uint id) ...@@ -146,6 +146,16 @@ bool Item_func::check_loop(uint id)
DBUG_RETURN(0); DBUG_RETURN(0);
} }
void Item_func::set_outer_resolving()
{
if (arg_count)
{
Item **arg,**arg_end;
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
(*arg)->set_outer_resolving();
}
}
void Item_func::split_sum_func(List<Item> &fields) void Item_func::split_sum_func(List<Item> &fields)
{ {
Item **arg,**arg_end; Item **arg,**arg_end;
...@@ -2356,6 +2366,15 @@ bool Item_func_match::check_loop(uint id) ...@@ -2356,6 +2366,15 @@ bool Item_func_match::check_loop(uint id)
DBUG_RETURN(0); DBUG_RETURN(0);
} }
void Item_func_match::set_outer_resolving()
{
Item_real_func::set_outer_resolving();
List_iterator<Item> li(fields);
Item *item;
while ((item= li++))
item->set_outer_resolving();
}
bool Item_func_match::fix_index() bool Item_func_match::fix_index()
{ {
List_iterator_fast<Item> li(fields); List_iterator_fast<Item> li(fields);
......
...@@ -133,6 +133,7 @@ class Item_func :public Item_result_field ...@@ -133,6 +133,7 @@ class Item_func :public Item_result_field
friend class udf_handler; friend class udf_handler;
Field *tmp_table_field(TABLE *t_arg); Field *tmp_table_field(TABLE *t_arg);
bool check_loop(uint id); bool check_loop(uint id);
void set_outer_resolving();
}; };
...@@ -632,6 +633,11 @@ class Item_func_field :public Item_int_func ...@@ -632,6 +633,11 @@ class Item_func_field :public Item_int_func
DBUG_RETURN(1); DBUG_RETURN(1);
DBUG_RETURN(item->check_loop(id)); DBUG_RETURN(item->check_loop(id));
} }
void set_outer_resolving()
{
item->set_outer_resolving();
Item_int_func::set_outer_resolving();
}
}; };
...@@ -1006,6 +1012,7 @@ class Item_func_match :public Item_real_func ...@@ -1006,6 +1012,7 @@ class Item_func_match :public Item_real_func
bool fix_index(); bool fix_index();
void init_search(bool no_order); void init_search(bool no_order);
bool check_loop(uint id); bool check_loop(uint id);
void set_outer_resolving();
}; };
......
...@@ -105,5 +105,20 @@ void Item_row::bring_value() ...@@ -105,5 +105,20 @@ void Item_row::bring_value()
{ {
for (uint i= 0; i < arg_count; i++) for (uint i= 0; i < arg_count; i++)
items[i]->bring_value(); items[i]->bring_value();
return; }
void Item_row::set_outer_resolving()
{
for (uint i= 0; i < arg_count; i++)
items[i]->set_outer_resolving();
}
bool Item_row::check_loop(uint id)
{
if (Item::check_loop(id))
return 1;
for (uint i= 0; i < arg_count; i++)
if (items[i]->check_loop(id))
return 1;
return 0;
} }
...@@ -64,6 +64,8 @@ class Item_row: public Item ...@@ -64,6 +64,8 @@ class Item_row: public Item
bool const_item() const { return const_item_cache; }; bool const_item() const { return const_item_cache; };
enum Item_result result_type() const { return ROW_RESULT; } enum Item_result result_type() const { return ROW_RESULT; }
void update_used_tables(); void update_used_tables();
bool check_loop(uint id);
void set_outer_resolving();
uint cols() { return arg_count; } uint cols() { return arg_count; }
Item* el(uint i) { return items[i]; } Item* el(uint i) { return items[i]; }
......
...@@ -108,14 +108,19 @@ class Item_func_concat_ws :public Item_str_func ...@@ -108,14 +108,19 @@ class Item_func_concat_ws :public Item_str_func
separator->fix_fields(thd, tlist, &separator) || separator->fix_fields(thd, tlist, &separator) ||
Item_func::fix_fields(thd, tlist, ref)); Item_func::fix_fields(thd, tlist, ref));
} }
const char *func_name() const { return "concat_ws"; } const char *func_name() const { return "concat_ws"; }
bool check_loop(uint id) bool check_loop(uint id)
{ {
DBUG_ENTER("Item_func_concat_ws::check_loop"); DBUG_ENTER("Item_func_concat_ws::check_loop");
if (Item_str_func::check_loop(id)) if (Item_str_func::check_loop(id))
DBUG_RETURN(1); DBUG_RETURN(1);
DBUG_RETURN(separator->check_loop(id)); DBUG_RETURN(separator->check_loop(id));
} }
void set_outer_resolving()
{
separator->set_outer_resolving();
Item_func::set_outer_resolving();
}
}; };
class Item_func_reverse :public Item_str_func class Item_func_reverse :public Item_str_func
...@@ -393,6 +398,11 @@ class Item_func_elt :public Item_str_func ...@@ -393,6 +398,11 @@ class Item_func_elt :public Item_str_func
DBUG_RETURN(1); DBUG_RETURN(1);
DBUG_RETURN(item->check_loop(id)); DBUG_RETURN(item->check_loop(id));
} }
void set_outer_resolving()
{
item->set_outer_resolving();
Item_str_func::set_outer_resolving();
}
}; };
...@@ -421,6 +431,11 @@ class Item_func_make_set :public Item_str_func ...@@ -421,6 +431,11 @@ class Item_func_make_set :public Item_str_func
DBUG_RETURN(1); DBUG_RETURN(1);
DBUG_RETURN(item->check_loop(id)); DBUG_RETURN(item->check_loop(id));
} }
void set_outer_resolving()
{
item->set_outer_resolving();
Item_str_func::set_outer_resolving();
}
}; };
......
...@@ -146,6 +146,54 @@ void Item_singlerow_subselect::reset() ...@@ -146,6 +146,54 @@ void Item_singlerow_subselect::reset()
value->null_value= 1; value->null_value= 1;
} }
void Item_singlerow_subselect::select_transformer(st_select_lex_unit *unit)
{
SELECT_LEX *select_lex= unit->first_select();
if (!select_lex->next_select() && !select_lex->table_list.elements &&
select_lex->item_list.elements == 1)
{
have_to_be_excluded= 1;
THD *thd= current_thd;
if (thd->lex.describe)
{
char warn_buff[MYSQL_ERRMSG_SIZE];
sprintf(warn_buff, ER(ER_SELECT_REDUCED), select_lex->select_number);
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_SELECT_REDUCED, warn_buff);
}
substitution= select_lex->item_list.head();
substitution->set_outer_resolving();
if (substitution->type() == FIELD_ITEM ||
substitution->type() == REF_ITEM)
name= substitution->name; // Save name for correct resolving
if (select_lex->where || select_lex->having)
{
Item *cond;
if (!select_lex->having)
cond= select_lex->where;
else if (!select_lex->where)
cond= select_lex->having;
else
if (!(cond= new Item_cond_and(select_lex->having, select_lex->where)))
{
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
thd->fatal_error= 1;
return;
}
if (!(substitution= new Item_func_if(cond, substitution,
new Item_null())))
{
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
thd->fatal_error= 1;
return;
}
}
}
}
void Item_singlerow_subselect::store(uint i, Item *item) void Item_singlerow_subselect::store(uint i, Item *item)
{ {
row[i]->store(item); row[i]->store(item);
......
...@@ -106,6 +106,7 @@ class Item_singlerow_subselect :public Item_subselect ...@@ -106,6 +106,7 @@ class Item_singlerow_subselect :public Item_subselect
decimals= item->decimals; decimals= item->decimals;
} }
void reset(); void reset();
void select_transformer(st_select_lex_unit *unit);
void store(uint i, Item* item); void store(uint i, Item* item);
double val(); double val();
longlong val_int (); longlong val_int ();
......
...@@ -463,7 +463,7 @@ bool drop_locked_tables(THD *thd,const char *db, const char *table_name); ...@@ -463,7 +463,7 @@ bool drop_locked_tables(THD *thd,const char *db, const char *table_name);
void abort_locked_tables(THD *thd,const char *db, const char *table_name); void abort_locked_tables(THD *thd,const char *db, const char *table_name);
extern const Field *not_found_field; extern const Field *not_found_field;
Field *find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, Field *find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
bool report_error); TABLE_LIST **where, bool report_error);
Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length, Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
bool check_grant,bool allow_rowid); bool check_grant,bool allow_rowid);
#ifdef HAVE_OPENSSL #ifdef HAVE_OPENSSL
......
...@@ -1654,6 +1654,7 @@ const Field *not_found_field= (Field*) 0x1; ...@@ -1654,6 +1654,7 @@ const Field *not_found_field= (Field*) 0x1;
thd - pointer to current thread structure thd - pointer to current thread structure
item - field item that should be found item - field item that should be found
tables - tables for scaning tables - tables for scaning
where - table where field found will be returned via this parameter
report_error - if FALSE then do not report error if item not found and report_error - if FALSE then do not report error if item not found and
return not_found_field; return not_found_field;
...@@ -1667,7 +1668,7 @@ const Field *not_found_field= (Field*) 0x1; ...@@ -1667,7 +1668,7 @@ const Field *not_found_field= (Field*) 0x1;
Field * Field *
find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
bool report_error) TABLE_LIST **where, bool report_error)
{ {
Field *found=0; Field *found=0;
const char *db=item->db_name; const char *db=item->db_name;
...@@ -1688,6 +1689,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, ...@@ -1688,6 +1689,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
grant_option && !thd->master_access,1); grant_option && !thd->master_access,1);
if (find) if (find)
{ {
(*where)= tables;
if (find == WRONG_GRANT) if (find == WRONG_GRANT)
return (Field*) 0; return (Field*) 0;
if (db || !thd->where) if (db || !thd->where)
...@@ -1742,6 +1744,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, ...@@ -1742,6 +1744,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
{ {
if (field == WRONG_GRANT) if (field == WRONG_GRANT)
return (Field*) 0; return (Field*) 0;
(*where)= tables;
if (found) if (found)
{ {
if (!thd->where) // Returns first found if (!thd->where) // Returns first found
......
...@@ -63,6 +63,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t) ...@@ -63,6 +63,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
TMP_TABLE_PARAM tmp_table_param; TMP_TABLE_PARAM tmp_table_param;
bool is_union=sl->next_select() && sl->next_select()->linkage == UNION_TYPE; bool is_union=sl->next_select() && sl->next_select()->linkage == UNION_TYPE;
DBUG_ENTER("mysql_derived"); DBUG_ENTER("mysql_derived");
SELECT_LEX_NODE *save_current_select= lex->current_select;
/* /*
...@@ -111,6 +112,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t) ...@@ -111,6 +112,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
} }
} }
lex->current_select= sl;
if (setup_fields(thd,tables,item_list,0,0,1)) if (setup_fields(thd,tables,item_list,0,0,1))
{ {
res=-1; res=-1;
...@@ -119,7 +121,8 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t) ...@@ -119,7 +121,8 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
bzero((char*) &tmp_table_param,sizeof(tmp_table_param)); bzero((char*) &tmp_table_param,sizeof(tmp_table_param));
tmp_table_param.field_count=item_list.elements; tmp_table_param.field_count=item_list.elements;
if (!(table=create_tmp_table(thd, &tmp_table_param, item_list, if (!(table=create_tmp_table(thd, &tmp_table_param, item_list,
(ORDER*) 0, is_union && !unit->union_option, 1, (ORDER*) 0,
is_union && !unit->union_option, 1,
(sl->options | thd->options | (sl->options | thd->options |
TMP_TABLE_ALL_COLUMNS), TMP_TABLE_ALL_COLUMNS),
HA_POS_ERROR))) HA_POS_ERROR)))
...@@ -138,8 +141,6 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t) ...@@ -138,8 +141,6 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
if (unit->select_limit_cnt == HA_POS_ERROR) if (unit->select_limit_cnt == HA_POS_ERROR)
sl->options&= ~OPTION_FOUND_ROWS; sl->options&= ~OPTION_FOUND_ROWS;
SELECT_LEX_NODE *save_current_select= lex->current_select;
lex->current_select= sl;
if (is_union) if (is_union)
res=mysql_union(thd,lex,derived_result,unit); res=mysql_union(thd,lex,derived_result,unit);
else else
...@@ -149,7 +150,6 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t) ...@@ -149,7 +150,6 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
sl->having, (ORDER*) NULL, sl->having, (ORDER*) NULL,
sl->options | thd->options | SELECT_NO_UNLOCK, sl->options | thd->options | SELECT_NO_UNLOCK,
derived_result, unit, sl, 0); derived_result, unit, sl, 0);
lex->current_select= save_current_select;
if (!res) if (!res)
{ {
...@@ -184,6 +184,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t) ...@@ -184,6 +184,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
if (res) if (res)
free_tmp_table(thd,table); free_tmp_table(thd,table);
exit: exit:
lex->current_select= save_current_select;
close_thread_tables(thd); close_thread_tables(thd);
} }
DBUG_RETURN(res); DBUG_RETURN(res);
......
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