Commit 06e64747 authored by unknown's avatar unknown

Reference to field in outer subelect fixed

Fixed context in error mesages


mysql-test/r/subselect.result:
  tests of references and error message
mysql-test/t/subselect.test:
  tests of references and error message
sql/item.cc:
  Fixed layout
  Resolving field names of outer select
sql/item_subselect.cc:
  saving/restoring context for error messages
sql/mysql_priv.h:
  changed function interface to allow resolving field names inside Item_ref::fix_fields
sql/sql_base.cc:
  changed function interface to allow resolving field names inside Item_ref::fix_fields
sql/sql_lex.h:
  allow access to thd field
parent 83e25bbc
......@@ -17,6 +17,16 @@ SELECT (SELECT 1),MAX(1) FROM (SELECT 1);
1 1
SELECT (SELECT a) as a;
Reference 'a' not supported (forward reference in item list)
EXPLAIN SELECT 1 FROM (SELECT 1 as a) HAVING (SELECT a)=1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 1
3 DEPENDENT SUBSELECT No tables used
2 DERIVED No tables used
SELECT 1 FROM (SELECT 1 as a) HAVING (SELECT a)=1;
1
1
SELECT (SELECT 1), a;
Unknown column 'a' in 'field list'
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8;
create table t1 (a int);
create table t2 (a int, b int);
......
......@@ -8,6 +8,10 @@ SELECT (SELECT 1 FROM (SELECT 1) HAVING b=1) as a,(SELECT 1 FROM (SELECT 1) HAVI
SELECT (SELECT 1),MAX(1) FROM (SELECT 1);
-- error 1245
SELECT (SELECT a) as a;
EXPLAIN SELECT 1 FROM (SELECT 1 as a) HAVING (SELECT a)=1;
SELECT 1 FROM (SELECT 1 as a) HAVING (SELECT a)=1;
-- error 1054
SELECT (SELECT 1), a;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8;
create table t1 (a int);
create table t2 (a int, b int);
......
......@@ -468,7 +468,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
(last= sl)->get_table_list(),
0)) != not_found_field)
break;
if((refer= find_item_in_list(this, (last= sl)->item_list,
if ((refer= find_item_in_list(this, sl->item_list,
REPORT_EXCEPT_NOT_FOUND)) !=
(Item **)not_found_item)
break;
......@@ -867,6 +867,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
REPORT_ALL_ERRORS))) ==
(Item **)not_found_item)
{
Field *tmp= (Field*) not_found_field;
/*
We can't find table field in table list of current select,
consequently we have to find it in outer subselect(s).
......@@ -878,16 +879,21 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
*/
SELECT_LEX *last=0;
for ( ; sl ; sl= sl->outer_select())
if((ref= find_item_in_list(this, (last= sl)->item_list,
{
if ((ref= find_item_in_list(this, (last= sl)->item_list,
REPORT_EXCEPT_NOT_FOUND)) !=
(Item **)not_found_item)
break;
if ((tmp= find_field_in_tables(thd, this,
sl->get_table_list(),
0)) != not_found_field);
}
if (!ref)
{
return 1;
}
else if (ref == (Item **)not_found_item)
else if (!tmp)
return -1;
else if (ref == (Item **)not_found_item && tmp == not_found_field)
{
// Call to report error
find_item_in_list(this,
......@@ -896,6 +902,16 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
ref= 0;
return 1;
}
else if (tmp != not_found_field)
{
ref= 0; // To prevent "delete *ref;" on ~Item_erf() of this item
Item_field* f;
if (!((*reference)= f= new Item_field(tmp)))
return 1;
f->depended_from= last;
thd->lex.current_select->mark_as_dependent(last);
return 0;
}
else
{
depended_from= last;
......
......@@ -81,6 +81,7 @@ void Item_subselect::make_field (Send_field *tmp_field)
bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
char const *save_where= thd->where;
int res= engine->prepare();
if (!res)
{
......@@ -93,6 +94,7 @@ bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
fix_length_and_dec();
}
fixed= 1;
thd->where= save_where;
return res;
}
......@@ -312,11 +314,13 @@ void subselect_union_engine::fix_length_and_dec()
int subselect_single_select_engine::exec()
{
DBUG_ENTER("subselect_single_select_engine::exec");
char const *save_where= join->thd->where;
if (!optimized)
{
optimized=1;
if (join->optimize())
{
join->thd->where= save_where;
executed= 1;
DBUG_RETURN(join->error?join->error:1);
}
......@@ -324,7 +328,10 @@ int subselect_single_select_engine::exec()
if (select_lex->dependent && executed)
{
if (join->reinit())
{
join->thd->where= save_where;
DBUG_RETURN(1);
}
item->assign_null();
item->assigned((executed= 0));
}
......@@ -335,14 +342,19 @@ int subselect_single_select_engine::exec()
join->exec();
join->thd->lex.current_select= save_select;
executed= 1;
join->thd->where= save_where;
DBUG_RETURN(join->error||thd->fatal_error);
}
join->thd->where= save_where;
DBUG_RETURN(0);
}
int subselect_union_engine::exec()
{
return unit->exec();
char const *save_where= unit->thd->where;
int res= unit->exec();
unit->thd->where= save_where;
return res;
}
uint subselect_single_select_engine::cols()
......
......@@ -463,7 +463,7 @@ bool table_is_used(TABLE *table, bool wait_for_name_lock);
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);
extern const Field *not_found_field;
Field *find_field_in_tables(THD *thd, Item_field *item, TABLE_LIST *tables,
Field *find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
bool report_error);
Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
bool check_grant,bool allow_rowid);
......
......@@ -1861,7 +1861,7 @@ const Field *not_found_field= (Field*) 0x1;
*/
Field *
find_field_in_tables(THD *thd, Item_field *item, TABLE_LIST *tables,
find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
bool report_error)
{
Field *found=0;
......
......@@ -294,6 +294,7 @@ class st_select_lex_unit: public st_select_lex_node {
int cleanup();
friend void mysql_init_query(THD *thd);
friend int subselect_union_engine::exec();
private:
bool create_total_list_n_last_return(THD *thd, st_lex *lex,
TABLE_LIST ***result);
......
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