Commit e8e3f772 authored by unknown's avatar unknown

fixed couple of bugs in field/reference name resolution

fixed error handling in subselect fix_field


mysql-test/r/subselect.result:
  test of name resolution
mysql-test/t/subselect.test:
  test of name resolution
sql/item.cc:
  fixed couple of bugs in field/reference name resolution.
sql/item_subselect.cc:
  fixed error handling
sql/mysql_priv.h:
  fixed couple of bugs in field/reference name resolution.
sql/sql_base.cc:
  fixed couple of bugs in field/reference name resolution.
sql/sql_select.cc:
  new find_item_in_list interface
parent 956c993f
...@@ -131,6 +131,8 @@ patient_uq clinic_uq ...@@ -131,6 +131,8 @@ patient_uq clinic_uq
1 1 1 1
1 2 1 2
2 2 2 2
select * from t1 where a= (select a from t2,t4 where t2.b=t4.b);
Column: 'a' in field list is ambiguous
drop table if exists t1,t2,t3; drop table if exists t1,t2,t3;
CREATE TABLE t3 (a varchar(20),b char(1) NOT NULL default '0'); CREATE TABLE t3 (a varchar(20),b char(1) NOT NULL default '0');
INSERT INTO t3 VALUES ('W','a'),('A','c'),('J','b'); INSERT INTO t3 VALUES ('W','a'),('A','c'),('J','b');
...@@ -159,4 +161,4 @@ INSERT INTO inscrit (pseudo,email) VALUES ('joce1','test1'); ...@@ -159,4 +161,4 @@ INSERT INTO inscrit (pseudo,email) VALUES ('joce1','test1');
INSERT INTO inscrit (pseudo,email) VALUES ('2joce1','2test1'); INSERT INTO inscrit (pseudo,email) VALUES ('2joce1','2test1');
SELECT pseudo FROM inscrit WHERE pseudo=(SELECT pseudo FROM inscrit WHERE pseudo LIKE '%joce%'); SELECT pseudo FROM inscrit WHERE pseudo=(SELECT pseudo FROM inscrit WHERE pseudo LIKE '%joce%');
Subselect returns more than 1 record Subselect returns more than 1 record
drop table if exists inscrit; drop table if exists t1,t2,t3,t4,t5,attend,clinic,inscrit;
...@@ -53,6 +53,10 @@ insert into clinic values(1,"Oblastnaia bolnitsa"),(2,"Bolnitsa Krasnogo Kresta" ...@@ -53,6 +53,10 @@ insert into clinic values(1,"Oblastnaia bolnitsa"),(2,"Bolnitsa Krasnogo Kresta"
insert into attend values (1,1),(1,2),(2,2),(1,3); insert into attend values (1,1),(1,2),(2,2),(1,3);
select * from attend where exists (select * from clinic where uq = clinic_uq); select * from attend where exists (select * from clinic where uq = clinic_uq);
# not unique fields
-- error 1052
select * from t1 where a= (select a from t2,t4 where t2.b=t4.b);
# different tipes & group functions # different tipes & group functions
drop table if exists t1,t2,t3; drop table if exists t1,t2,t3;
...@@ -81,4 +85,4 @@ INSERT INTO inscrit (pseudo,email) VALUES ('2joce1','2test1'); ...@@ -81,4 +85,4 @@ INSERT INTO inscrit (pseudo,email) VALUES ('2joce1','2test1');
-- error 1240 -- error 1240
SELECT pseudo FROM inscrit WHERE pseudo=(SELECT pseudo FROM inscrit WHERE pseudo LIKE '%joce%'); SELECT pseudo FROM inscrit WHERE pseudo=(SELECT pseudo FROM inscrit WHERE pseudo LIKE '%joce%');
drop table if exists inscrit; drop table if exists t1,t2,t3,t4,t5,attend,clinic,inscrit;
\ No newline at end of file \ No newline at end of file
...@@ -432,7 +432,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ...@@ -432,7 +432,7 @@ 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; Field *tmp;
if (!(tmp=find_field_in_tables(thd, this, tables, 0))) if ((tmp= find_field_in_tables(thd, this, tables, 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,
...@@ -445,14 +445,18 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ...@@ -445,14 +445,18 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
*/ */
SELECT_LEX *last= 0; SELECT_LEX *last= 0;
for (SELECT_LEX *sl= thd->lex.select->outer_select(); for (SELECT_LEX *sl= thd->lex.select->outer_select();
sl && !tmp; sl;
sl= sl->outer_select()) sl= sl->outer_select())
tmp=find_field_in_tables(thd, this, if ((tmp= find_field_in_tables(thd, this,
(TABLE_LIST*)(last= sl)->table_list.first, (TABLE_LIST*)
0); (last= sl)->table_list.first,
0)) != not_found_field)
break;
if (!tmp) if (!tmp)
return -1;
else if (tmp == not_found_field)
{ {
// Call to produce appropriate error message // call to return error code
find_field_in_tables(thd, this, tables, 1); find_field_in_tables(thd, this, tables, 1);
return -1; return -1;
} }
...@@ -478,7 +482,10 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ...@@ -478,7 +482,10 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
tbl->shared= 1; tbl->shared= 1;
} }
} }
} }
else if (!tmp)
return -1;
set_field(tmp); set_field(tmp);
} }
else if (thd && thd->set_query_id && field->query_id != thd->query_id) else if (thd && thd->set_query_id && field->query_id != thd->query_id)
...@@ -786,7 +793,9 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) ...@@ -786,7 +793,9 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
{ {
if (!ref) if (!ref)
{ {
if (!(ref= find_item_in_list(this, thd->lex.select->item_list, 0))) if ((ref= find_item_in_list(this, thd->lex.select->item_list,
REPORT_EXCEPT_NOT_FOUND)) ==
not_found_item)
{ {
/* /*
We can't find table field in table list of current select, We can't find table field in table list of current select,
...@@ -795,17 +804,25 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) ...@@ -795,17 +804,25 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
of view rules. For example if both tables (outer & current) have of view rules. For example if both tables (outer & current) have
field 'field' it is not mistake to refer to this field without field 'field' it is not mistake to refer to this field without
mention of table name, but if we join tables in one list it will mention of table name, but if we join tables in one list it will
cause error ER_NON_UNIQ_ERROR in find_field_in_tables. cause error ER_NON_UNIQ_ERROR in find_item_in_list.
*/ */
SELECT_LEX *last=0; SELECT_LEX *last=0;
for (SELECT_LEX *sl= thd->lex.select->outer_select(); for (SELECT_LEX *sl= thd->lex.select->outer_select();
sl && !ref; sl;
sl= sl->outer_select()) sl= sl->outer_select())
ref= find_item_in_list(this, (last= sl)->item_list, 0); if((ref= find_item_in_list(this, (last= sl)->item_list,
REPORT_EXCEPT_NOT_FOUND)) !=
not_found_item)
break;
if (!ref) if (!ref)
{
return 1;
}
else if (ref == not_found_item)
{ {
// Call to report error // Call to report error
find_item_in_list(this, thd->lex.select->item_list, 1); find_item_in_list(this, thd->lex.select->item_list, REPORT_ALL_ERRORS);
return 1; return 1;
} }
else else
...@@ -831,6 +848,8 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) ...@@ -831,6 +848,8 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
} }
} }
} }
else if (!ref)
return 1;
max_length= (*ref)->max_length; max_length= (*ref)->max_length;
maybe_null= (*ref)->maybe_null; maybe_null= (*ref)->maybe_null;
decimals= (*ref)->decimals; decimals= (*ref)->decimals;
......
...@@ -83,7 +83,8 @@ bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ...@@ -83,7 +83,8 @@ bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
return 1; return 1;
} }
int res= engine->prepare(); int res= engine->prepare();
fix_length_and_dec(); if (!res)
fix_length_and_dec();
return res; return res;
} }
......
...@@ -456,6 +456,7 @@ bool wait_for_tables(THD *thd); ...@@ -456,6 +456,7 @@ bool wait_for_tables(THD *thd);
bool table_is_used(TABLE *table, bool wait_for_name_lock); 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;
Field *find_field_in_tables(THD *thd, Item_field *item, TABLE_LIST *tables, Field *find_field_in_tables(THD *thd, Item_field *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,
...@@ -545,7 +546,11 @@ TABLE *unlink_open_table(THD *thd,TABLE *list,TABLE *find); ...@@ -545,7 +546,11 @@ TABLE *unlink_open_table(THD *thd,TABLE *list,TABLE *find);
SQL_SELECT *make_select(TABLE *head, table_map const_tables, SQL_SELECT *make_select(TABLE *head, table_map const_tables,
table_map read_tables, COND *conds, int *error); table_map read_tables, COND *conds, int *error);
Item ** find_item_in_list(Item *item, List<Item> &items, bool report_error); enum find_item_error_report_type {REPORT_ALL_ERRORS, REPORT_EXCEPT_NOT_FOUND,
IGNORE_ERRORS};
extern const Item **not_found_item;
Item ** find_item_in_list(Item *item, List<Item> &items,
find_item_error_report_type report_error);
bool insert_fields(THD *thd,TABLE_LIST *tables, bool insert_fields(THD *thd,TABLE_LIST *tables,
const char *db_name, const char *table_name, const char *db_name, const char *table_name,
List_iterator<Item> *it); List_iterator<Item> *it);
......
...@@ -1781,9 +1781,29 @@ Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length, ...@@ -1781,9 +1781,29 @@ Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
return field; return field;
} }
// Special Field pointer for find_field_in_tables returning
const Field *not_found_field= (Field*) 0x1;
/*
Find field in table list.
SYNOPSIS
find_field_in_tables()
thd - pointer to current thread structure
item - field item that should be found
tables - tables for scaning
report_error - if FALSE then do not report error if item not found and
return not_found_field;
RETURN VALUES
0 - field is not found or field is not unique, error message is
reported
not_found_field - function was called with report_error == FALSE and
field if not found, no error message reported
found field
*/
Field * Field *
find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables, find_field_in_tables(THD *thd, Item_field *item, TABLE_LIST *tables,
bool report_error) bool report_error)
{ {
Field *found=0; Field *found=0;
...@@ -1829,13 +1849,18 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables, ...@@ -1829,13 +1849,18 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables,
strxnmov(buff,sizeof(buff)-1,db,".",table_name,NullS); strxnmov(buff,sizeof(buff)-1,db,".",table_name,NullS);
table_name=buff; table_name=buff;
} }
my_printf_error(ER_UNKNOWN_TABLE,ER(ER_UNKNOWN_TABLE),MYF(0),table_name, if (report_error)
thd->where); my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0),
table_name, thd->where);
else
return (Field*) not_found_field;
} }
else else
if (report_error) if (report_error)
my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),MYF(0), my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),MYF(0),
item->full_name(),thd->where); item->full_name(),thd->where);
else
return (Field*) not_found_field;
return (Field*) 0; return (Field*) 0;
} }
bool allow_rowid= tables && !tables->next; // Only one table bool allow_rowid= tables && !tables->next; // Only one table
...@@ -1850,11 +1875,10 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables, ...@@ -1850,11 +1875,10 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables,
return (Field*) 0; return (Field*) 0;
if (found) if (found)
{ {
if (!report_error) // Returns first found if (!thd->where) // Returns first found
break; break;
if (report_error) my_printf_error(ER_NON_UNIQ_ERROR,ER(ER_NON_UNIQ_ERROR),MYF(0),
my_printf_error(ER_NON_UNIQ_ERROR,ER(ER_NON_UNIQ_ERROR),MYF(0), name,thd->where);
name,thd->where);
return (Field*) 0; return (Field*) 0;
} }
found=field; found=field;
...@@ -1865,11 +1889,39 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables, ...@@ -1865,11 +1889,39 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables,
if (report_error) if (report_error)
my_printf_error(ER_BAD_FIELD_ERROR, ER(ER_BAD_FIELD_ERROR), my_printf_error(ER_BAD_FIELD_ERROR, ER(ER_BAD_FIELD_ERROR),
MYF(0), item->full_name(), thd->where); MYF(0), item->full_name(), thd->where);
else
return (Field*) not_found_field;
return (Field*) 0; return (Field*) 0;
} }
// Special Item pointer for find_item_in_list returning
const Item **not_found_item= (const Item**) 0x1;
/*
Find Item in list of items (find_field_in_tables analog)
SYNOPSIS
find_item_in_list()
find - item to find
items - list of items
report_error
REPORT_ALL_ERRORS - report errors, return 0 if error
REPORT_EXCEPT_NOT_FOUND - do not report 'not found' error and return not_ found_item, report other errors, return 0
IGNORE_ERRORS - do not report errors, return 0 if error
RETURN VALUES
0 - item is not found or item is not unique, error message is
reported
not_found_item - function was called with report_error ==
REPORT_EXCEPT_NOT_FOUND and item if not found, no error
message reported
found field
*/
Item ** Item **
find_item_in_list(Item *find, List<Item> &items, bool report_error) find_item_in_list(Item *find, List<Item> &items,
find_item_error_report_type report_error)
{ {
List_iterator<Item> li(items); List_iterator<Item> li(items);
Item **found=0,*item; Item **found=0,*item;
...@@ -1894,7 +1946,7 @@ find_item_in_list(Item *find, List<Item> &items, bool report_error) ...@@ -1894,7 +1946,7 @@ find_item_in_list(Item *find, List<Item> &items, bool report_error)
{ {
if ((*found)->eq(item,0)) if ((*found)->eq(item,0))
continue; // Same field twice (Access?) continue; // Same field twice (Access?)
if (report_error) if (report_error != IGNORE_ERRORS)
my_printf_error(ER_NON_UNIQ_ERROR,ER(ER_NON_UNIQ_ERROR),MYF(0), my_printf_error(ER_NON_UNIQ_ERROR,ER(ER_NON_UNIQ_ERROR),MYF(0),
find->full_name(), current_thd->where); find->full_name(), current_thd->where);
return (Item**) 0; return (Item**) 0;
...@@ -1917,10 +1969,17 @@ find_item_in_list(Item *find, List<Item> &items, bool report_error) ...@@ -1917,10 +1969,17 @@ find_item_in_list(Item *find, List<Item> &items, bool report_error)
break; break;
} }
} }
if (!found && report_error) if (found)
my_printf_error(ER_BAD_FIELD_ERROR, ER(ER_BAD_FIELD_ERROR), MYF(0), return found;
find->full_name(), current_thd->where); else if (report_error != REPORT_EXCEPT_NOT_FOUND)
return found; {
if (report_error == REPORT_ALL_ERRORS)
my_printf_error(ER_BAD_FIELD_ERROR, ER(ER_BAD_FIELD_ERROR), MYF(0),
find->full_name(), current_thd->where);
return (Item **) 0;
}
else
return (Item **) not_found_item;
} }
/**************************************************************************** /****************************************************************************
......
...@@ -6487,7 +6487,7 @@ find_order_in_list(THD *thd,TABLE_LIST *tables,ORDER *order,List<Item> &fields, ...@@ -6487,7 +6487,7 @@ find_order_in_list(THD *thd,TABLE_LIST *tables,ORDER *order,List<Item> &fields,
order->in_field_list=1; order->in_field_list=1;
return 0; return 0;
} }
Item **item=find_item_in_list(*order->item, fields, 0); Item **item= find_item_in_list(*order->item, fields, IGNORE_ERRORS);
if (item) if (item)
{ {
order->item=item; // use it order->item=item; // use it
...@@ -6587,7 +6587,7 @@ setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields, ...@@ -6587,7 +6587,7 @@ setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
thd->set_query_id=1; // Not really needed, but... thd->set_query_id=1; // Not really needed, but...
for (; new_field ; new_field= new_field->next) for (; new_field ; new_field= new_field->next)
{ {
if ((item= find_item_in_list(*new_field->item, fields, 0))) if ((item= find_item_in_list(*new_field->item, fields, IGNORE_ERRORS)))
new_field->item=item; /* Change to shared Item */ new_field->item=item; /* Change to shared Item */
else else
{ {
......
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