Commit baf0c9ad authored by evgen@moonbone.local's avatar evgen@moonbone.local

Fix bug #11864 non unique names are allowed in subquery

Column names weren't checked for uniqueness for subqueries.

Code for names uniqueness checking used for view creation moved into 
separate function named check_duplicate_names(). It's called on 
preparation of subqueries to check uniqueness of names. If duplicate names 
are found then error is raised.
parent 5d3b4067
...@@ -111,7 +111,7 @@ a b ...@@ -111,7 +111,7 @@ a b
1 a 1 a
2 b 2 b
3 c 3 c
explain select * from (select * from t1,t2 where t1.a=t2.a) t1; explain select * from (select t1.*, t2.a as t2a from t1,t2 where t1.a=t2.a) t1;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 1 1 PRIMARY <derived2> system NULL NULL NULL NULL 1
2 DERIVED t2 system NULL NULL NULL NULL 1 2 DERIVED t2 system NULL NULL NULL NULL 1
...@@ -363,3 +363,8 @@ a ...@@ -363,3 +363,8 @@ a
3 3
3 3
drop table t1, t2, t3; drop table t1, t2, t3;
create table t1 (a int);
create table t2 (a int);
select * from (select * from t1,t2) foo;
ERROR 42S21: Duplicate column name 'a'
drop table t1,t2;
...@@ -84,7 +84,7 @@ set local max_join_size=8; ...@@ -84,7 +84,7 @@ set local max_join_size=8;
select * from (select * from t1) x; select * from (select * from t1) x;
ERROR 42000: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is okay ERROR 42000: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is okay
set local max_join_size=1; set local max_join_size=1;
select * from (select * from t1 a, t1 b) x; select * from (select a.a as aa, b.a as ba from t1 a, t1 b) x;
ERROR 42000: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is okay ERROR 42000: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is okay
set local max_join_size=1; set local max_join_size=1;
select * from (select 1 union select 2 union select 3) x; select * from (select 1 union select 2 union select 3) x;
......
...@@ -42,7 +42,7 @@ CREATE TABLE t2 (a int not null); ...@@ -42,7 +42,7 @@ CREATE TABLE t2 (a int not null);
insert into t2 values(1); insert into t2 values(1);
select * from (select * from t1 where t1.a=(select a from t2 where t2.a=t1.a)) a; select * from (select * from t1 where t1.a=(select a from t2 where t2.a=t1.a)) a;
select * from (select * from t1 where t1.a=(select t2.a from t2 where t2.a=t1.a) union select t1.a, t1.b from t1) a; select * from (select * from t1 where t1.a=(select t2.a from t2 where t2.a=t1.a) union select t1.a, t1.b from t1) a;
explain select * from (select * from t1,t2 where t1.a=t2.a) t1; explain select * from (select t1.*, t2.a as t2a from t1,t2 where t1.a=t2.a) t1;
drop table t1, t2; drop table t1, t2;
create table t1(a int not null, t char(8), index(a)); create table t1(a int not null, t char(8), index(a));
disable_query_log; disable_query_log;
...@@ -249,4 +249,13 @@ select * from t1 union distinct select * from t2 union all select * from t3; ...@@ -249,4 +249,13 @@ select * from t1 union distinct select * from t2 union all select * from t3;
select * from (select * from t1 union distinct select * from t2 union all select * from t3) X; select * from (select * from t1 union distinct select * from t2 union all select * from t3) X;
drop table t1, t2, t3; drop table t1, t2, t3;
#
# Bug #11864 non unique names are allowed in subquery
#
create table t1 (a int);
create table t2 (a int);
--error 1060
select * from (select * from t1,t2) foo;
drop table t1,t2;
# End of 4.1 tests # End of 4.1 tests
...@@ -78,7 +78,7 @@ select * from (select * from t1) x; ...@@ -78,7 +78,7 @@ select * from (select * from t1) x;
set local max_join_size=1; set local max_join_size=1;
--error 1104 --error 1104
select * from (select * from t1 a, t1 b) x; select * from (select a.a as aa, b.a as ba from t1 a, t1 b) x;
set local max_join_size=1; set local max_join_size=1;
--error 1104 --error 1104
......
...@@ -125,6 +125,11 @@ int mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *orig_table_list) ...@@ -125,6 +125,11 @@ int mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *orig_table_list)
if ((res= unit->prepare(thd, derived_result, 0, orig_table_list->alias))) if ((res= unit->prepare(thd, derived_result, 0, orig_table_list->alias)))
goto exit; goto exit;
if (check_duplicate_names(unit->types, 0))
{
res= -1;
goto exit;
}
derived_result->tmp_table_param.init(); derived_result->tmp_table_param.init();
derived_result->tmp_table_param.field_count= unit->types.elements; derived_result->tmp_table_param.field_count= unit->types.elements;
......
...@@ -94,6 +94,71 @@ static void make_unique_view_field_name(Item *target, ...@@ -94,6 +94,71 @@ static void make_unique_view_field_name(Item *target,
target->set_name(buff, name_len, system_charset_info); target->set_name(buff, name_len, system_charset_info);
} }
/*
Check if items with same names are present in list and possibly
generate unique names for them.
SYNOPSIS
item_list list of Items which should be checked for duplicates
gen_unique_view_name flag: generate unique name or return with error when
duplicate names are found.
DESCRIPTION
This function is used on view creation and preparation of derived tables.
It checks item_list for items with duplicate names. If it founds two
items with same name and conversion to unique names isn't allowed, or
names for both items are set by user - function fails.
Otherwise it generates unique name for one item with autogenerated name
using make_unique_view_field_name()
RETURN VALUE
FALSE no duplicate names found, or they are converted to unique ones
TRUE duplicate names are found and they can't be converted or conversion
isn't allowed
*/
bool check_duplicate_names(List<Item> &item_list, bool gen_unique_view_name)
{
DBUG_ENTER("check_duplicate_names");
/* Test absence of duplicates names */
{
Item *item;
List_iterator_fast<Item> it(item_list);
List_iterator_fast<Item> itc(item_list);
while ((item= it++))
{
Item *check;
/* treat underlying fields like set by user names */
if (item->real_item()->type() == Item::FIELD_ITEM)
item->is_autogenerated_name= FALSE;
itc.rewind();
while ((check= itc++) && check != item)
{
if (my_strcasecmp(system_charset_info, item->name, check->name) == 0)
{
if (!gen_unique_view_name)
{
my_error(ER_DUP_FIELDNAME, MYF(0), item->name);
DBUG_RETURN(TRUE);
}
else if (item->is_autogenerated_name)
make_unique_view_field_name(item, item_list, item);
else if (check->is_autogenerated_name)
make_unique_view_field_name(check, item_list, item);
else
{
my_error(ER_DUP_FIELDNAME, MYF(0), item->name);
DBUG_RETURN(TRUE);
}
}
}
}
}
DBUG_RETURN(FALSE);
}
/* /*
Creating/altering VIEW procedure Creating/altering VIEW procedure
...@@ -308,35 +373,8 @@ bool mysql_create_view(THD *thd, ...@@ -308,35 +373,8 @@ bool mysql_create_view(THD *thd,
} }
} }
/* Test absence of duplicates names */ if (check_duplicate_names(select_lex->item_list, 1))
{ DBUG_RETURN(TRUE);
Item *item;
List_iterator_fast<Item> it(select_lex->item_list);
List_iterator_fast<Item> itc(select_lex->item_list);
while ((item= it++))
{
Item *check;
/* treat underlying fields like set by user names */
if (item->real_item()->type() == Item::FIELD_ITEM)
item->is_autogenerated_name= FALSE;
itc.rewind();
while ((check= itc++) && check != item)
{
if (my_strcasecmp(system_charset_info, item->name, check->name) == 0)
{
if (item->is_autogenerated_name)
make_unique_view_field_name(item, select_lex->item_list, item);
else if (check->is_autogenerated_name)
make_unique_view_field_name(check, select_lex->item_list, item);
else
{
my_error(ER_DUP_FIELDNAME, MYF(0), item->name);
DBUG_RETURN(TRUE);
}
}
}
}
}
#ifndef NO_EMBEDDED_ACCESS_CHECKS #ifndef NO_EMBEDDED_ACCESS_CHECKS
/* /*
......
...@@ -33,5 +33,7 @@ int view_checksum(THD *thd, TABLE_LIST *view); ...@@ -33,5 +33,7 @@ int view_checksum(THD *thd, TABLE_LIST *view);
extern TYPELIB updatable_views_with_limit_typelib; extern TYPELIB updatable_views_with_limit_typelib;
bool check_duplicate_names(List<Item>& item_list, bool gen_unique_view_names);
#define VIEW_ANY_ACL (SELECT_ACL | UPDATE_ACL | INSERT_ACL | DELETE_ACL) #define VIEW_ANY_ACL (SELECT_ACL | UPDATE_ACL | INSERT_ACL | DELETE_ACL)
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