1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

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
This commit is contained in:
unknown
2002-11-24 21:10:52 +02:00
parent 83e25bbc30
commit 06e647472f
7 changed files with 51 additions and 8 deletions

View File

@@ -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);

View File

@@ -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);

View File

@@ -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)
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)
*/ */
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)
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;

View File

@@ -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)
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()
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()
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()
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()

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);