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
This commit is contained in:
parent
956c993f64
commit
e8e3f7728f
@ -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');
|
|||||||
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"
|
|||||||
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');
|
|||||||
-- 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;
|
41
sql/item.cc
41
sql/item.cc
@ -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)
|
|||||||
*/
|
*/
|
||||||
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;
|
||||||
}
|
}
|
||||||
@ -479,6 +483,9 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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)
|
|||||||
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);
|
|||||||
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);
|
|||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
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
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user