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); ...@@ -17,6 +17,16 @@ SELECT (SELECT 1),MAX(1) FROM (SELECT 1);
1 1 1 1
SELECT (SELECT a) as a; SELECT (SELECT a) as a;
Reference 'a' not supported (forward reference in item list) 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; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8;
create table t1 (a int); create table t1 (a int);
create table t2 (a int, b 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 ...@@ -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); SELECT (SELECT 1),MAX(1) FROM (SELECT 1);
-- error 1245 -- error 1245
SELECT (SELECT a) as a; 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; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8;
create table t1 (a int); create table t1 (a int);
create table t2 (a int, b int); create table t2 (a int, b int);
......
...@@ -468,7 +468,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ...@@ -468,7 +468,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
(last= sl)->get_table_list(), (last= sl)->get_table_list(),
0)) != not_found_field) 0)) != not_found_field)
break; 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)) != REPORT_EXCEPT_NOT_FOUND)) !=
(Item **)not_found_item) (Item **)not_found_item)
break; break;
...@@ -867,6 +867,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) ...@@ -867,6 +867,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
REPORT_ALL_ERRORS))) == REPORT_ALL_ERRORS))) ==
(Item **)not_found_item) (Item **)not_found_item)
{ {
Field *tmp= (Field*) 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,
consequently we have to find it in outer subselect(s). 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) ...@@ -878,16 +879,21 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
*/ */
SELECT_LEX *last=0; SELECT_LEX *last=0;
for ( ; sl ; sl= sl->outer_select()) 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)) != REPORT_EXCEPT_NOT_FOUND)) !=
(Item **)not_found_item) (Item **)not_found_item)
break; break;
if ((tmp= find_field_in_tables(thd, this,
sl->get_table_list(),
0)) != not_found_field);
}
if (!ref) if (!ref)
{
return 1; return 1;
} else if (!tmp)
else if (ref == (Item **)not_found_item) return -1;
else if (ref == (Item **)not_found_item && tmp == not_found_field)
{ {
// Call to report error // Call to report error
find_item_in_list(this, find_item_in_list(this,
...@@ -896,6 +902,16 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) ...@@ -896,6 +902,16 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
ref= 0; ref= 0;
return 1; 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 else
{ {
depended_from= last; depended_from= last;
......
...@@ -81,6 +81,7 @@ void Item_subselect::make_field (Send_field *tmp_field) ...@@ -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) bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{ {
char const *save_where= thd->where;
int res= engine->prepare(); int res= engine->prepare();
if (!res) if (!res)
{ {
...@@ -93,6 +94,7 @@ bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ...@@ -93,6 +94,7 @@ bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
fix_length_and_dec(); fix_length_and_dec();
} }
fixed= 1; fixed= 1;
thd->where= save_where;
return res; return res;
} }
...@@ -312,11 +314,13 @@ void subselect_union_engine::fix_length_and_dec() ...@@ -312,11 +314,13 @@ void subselect_union_engine::fix_length_and_dec()
int subselect_single_select_engine::exec() int subselect_single_select_engine::exec()
{ {
DBUG_ENTER("subselect_single_select_engine::exec"); DBUG_ENTER("subselect_single_select_engine::exec");
char const *save_where= join->thd->where;
if (!optimized) if (!optimized)
{ {
optimized=1; optimized=1;
if (join->optimize()) if (join->optimize())
{ {
join->thd->where= save_where;
executed= 1; executed= 1;
DBUG_RETURN(join->error?join->error:1); DBUG_RETURN(join->error?join->error:1);
} }
...@@ -324,7 +328,10 @@ int subselect_single_select_engine::exec() ...@@ -324,7 +328,10 @@ int subselect_single_select_engine::exec()
if (select_lex->dependent && executed) if (select_lex->dependent && executed)
{ {
if (join->reinit()) if (join->reinit())
{
join->thd->where= save_where;
DBUG_RETURN(1); DBUG_RETURN(1);
}
item->assign_null(); item->assign_null();
item->assigned((executed= 0)); item->assigned((executed= 0));
} }
...@@ -335,14 +342,19 @@ int subselect_single_select_engine::exec() ...@@ -335,14 +342,19 @@ int subselect_single_select_engine::exec()
join->exec(); join->exec();
join->thd->lex.current_select= save_select; join->thd->lex.current_select= save_select;
executed= 1; executed= 1;
join->thd->where= save_where;
DBUG_RETURN(join->error||thd->fatal_error); DBUG_RETURN(join->error||thd->fatal_error);
} }
join->thd->where= save_where;
DBUG_RETURN(0); DBUG_RETURN(0);
} }
int subselect_union_engine::exec() 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() uint subselect_single_select_engine::cols()
......
...@@ -463,7 +463,7 @@ bool table_is_used(TABLE *table, bool wait_for_name_lock); ...@@ -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); 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_field *item, TABLE_LIST *tables, Field *find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
bool report_error); 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);
......
...@@ -1861,7 +1861,7 @@ const Field *not_found_field= (Field*) 0x1; ...@@ -1861,7 +1861,7 @@ const Field *not_found_field= (Field*) 0x1;
*/ */
Field * 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) bool report_error)
{ {
Field *found=0; Field *found=0;
......
...@@ -294,6 +294,7 @@ public: ...@@ -294,6 +294,7 @@ public:
int cleanup(); int cleanup();
friend void mysql_init_query(THD *thd); friend void mysql_init_query(THD *thd);
friend int subselect_union_engine::exec();
private: private:
bool create_total_list_n_last_return(THD *thd, st_lex *lex, bool create_total_list_n_last_return(THD *thd, st_lex *lex,
TABLE_LIST ***result); 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