Commit 32262a0f authored by bell@sanja.is.com.ua's avatar bell@sanja.is.com.ua

fixed subqueries name resolution with INSERT/REPLACE (found during bug 446 investigation)

parent 8d52377a
...@@ -580,12 +580,12 @@ a b ...@@ -580,12 +580,12 @@ a b
drop table t11, t12, t2; drop table t11, t12, t2;
CREATE TABLE t1 (x int); CREATE TABLE t1 (x int);
create table t2 (a int); create table t2 (a int);
create table t3 (a int); create table t3 (b int);
insert into t2 values (1); insert into t2 values (1);
insert into t3 values (1),(2); insert into t3 values (1),(2);
INSERT INTO t1 (x) VALUES ((SELECT x FROM t1)); INSERT INTO t1 (x) VALUES ((SELECT x FROM t1));
You can't specify target table 't1' for update in FROM clause You can't specify target table 't1' for update in FROM clause
INSERT INTO t1 (x) VALUES ((SELECT a FROM t3)); INSERT INTO t1 (x) VALUES ((SELECT b FROM t3));
Subselect returns more than 1 record Subselect returns more than 1 record
INSERT INTO t1 (x) VALUES ((SELECT a FROM t2)); INSERT INTO t1 (x) VALUES ((SELECT a FROM t2));
select * from t1; select * from t1;
...@@ -607,13 +607,15 @@ x ...@@ -607,13 +607,15 @@ x
INSERT INTO t1 (x) select (SELECT SUM(x)+2 FROM t1) FROM t2; INSERT INTO t1 (x) select (SELECT SUM(x)+2 FROM t1) FROM t2;
You can't specify target table 't1' for update in FROM clause You can't specify target table 't1' for update in FROM clause
INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(x) FROM t2)); INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(x) FROM t2));
Unknown column 'x' in 'field list'
INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(a) FROM t2));
select * from t1; select * from t1;
x x
1 1
2 2
3 3
3 3
0 2
drop table t1, t2, t3; drop table t1, t2, t3;
CREATE TABLE t1 (x int not null, y int, primary key (x)); CREATE TABLE t1 (x int not null, y int, primary key (x));
create table t2 (a int); create table t2 (a int);
......
...@@ -334,13 +334,13 @@ drop table t11, t12, t2; ...@@ -334,13 +334,13 @@ drop table t11, t12, t2;
#insert with subselects #insert with subselects
CREATE TABLE t1 (x int); CREATE TABLE t1 (x int);
create table t2 (a int); create table t2 (a int);
create table t3 (a int); create table t3 (b int);
insert into t2 values (1); insert into t2 values (1);
insert into t3 values (1),(2); insert into t3 values (1),(2);
-- error 1093 -- error 1093
INSERT INTO t1 (x) VALUES ((SELECT x FROM t1)); INSERT INTO t1 (x) VALUES ((SELECT x FROM t1));
-- error 1240 -- error 1240
INSERT INTO t1 (x) VALUES ((SELECT a FROM t3)); INSERT INTO t1 (x) VALUES ((SELECT b FROM t3));
INSERT INTO t1 (x) VALUES ((SELECT a FROM t2)); INSERT INTO t1 (x) VALUES ((SELECT a FROM t2));
select * from t1; select * from t1;
insert into t2 values (1); insert into t2 values (1);
...@@ -351,9 +351,15 @@ INSERT INTO t1 (x) select (SELECT SUM(a)+1 FROM t2) FROM t2; ...@@ -351,9 +351,15 @@ INSERT INTO t1 (x) select (SELECT SUM(a)+1 FROM t2) FROM t2;
select * from t1; select * from t1;
-- error 1093 -- error 1093
INSERT INTO t1 (x) select (SELECT SUM(x)+2 FROM t1) FROM t2; INSERT INTO t1 (x) select (SELECT SUM(x)+2 FROM t1) FROM t2;
-- error 1054
INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(x) FROM t2)); INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(x) FROM t2));
INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(a) FROM t2));
-- sleep 1 -- sleep 1
select * from t1; select * from t1;
#
#TODO: should be uncommented after bug 380 fix pushed
#INSERT INTO t1 (x) SELECT (SELECT SUM(a)+b FROM t2) from t3;
#select * from t1;
drop table t1, t2, t3; drop table t1, t2, t3;
#replace with subselects #replace with subselects
......
...@@ -758,6 +758,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ...@@ -758,6 +758,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
#ifdef EMBEDDED_LIBRARY #ifdef EMBEDDED_LIBRARY
thd->net.last_errno= 0; thd->net.last_errno= 0;
#endif #endif
TABLE_LIST *table_list;
Item **refer= (Item **)not_found_item; Item **refer= (Item **)not_found_item;
uint counter; uint counter;
// Prevent using outer fields in subselects, that is not supported now // Prevent using outer fields in subselects, that is not supported now
...@@ -768,8 +769,14 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ...@@ -768,8 +769,14 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
sl; sl;
sl= sl->outer_select()) sl= sl->outer_select())
{ {
table_list= (last= sl)->get_table_list();
if (sl->insert_select && table_list)
{
// it is primary INSERT st_select_lex => skip first table resolving
table_list= table_list->next;
}
if ((tmp= find_field_in_tables(thd, this, if ((tmp= find_field_in_tables(thd, this,
(last= sl)->get_table_list(), &where, table_list, &where,
0)) != not_found_field) 0)) != not_found_field)
break; break;
if ((refer= find_item_in_list(this, sl->item_list, &counter, if ((refer= find_item_in_list(this, sl->item_list, &counter,
...@@ -1221,7 +1228,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) ...@@ -1221,7 +1228,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
uint counter; uint counter;
if (!ref) if (!ref)
{ {
TABLE_LIST *where= 0; TABLE_LIST *where= 0, *table_list;
SELECT_LEX *sl= (outer_resolving? SELECT_LEX *sl= (outer_resolving?
thd->lex.current_select->select_lex(): thd->lex.current_select->select_lex():
thd->lex.current_select->outer_select()); thd->lex.current_select->outer_select());
...@@ -1260,8 +1267,14 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) ...@@ -1260,8 +1267,14 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
REPORT_EXCEPT_NOT_FOUND)) != REPORT_EXCEPT_NOT_FOUND)) !=
(Item **)not_found_item) (Item **)not_found_item)
break; break;
table_list= sl->get_table_list();
if (sl->insert_select && table_list)
{
// it is primary INSERT st_select_lex => skip first table resolving
table_list= table_list->next;
}
if ((tmp= find_field_in_tables(thd, this, if ((tmp= find_field_in_tables(thd, this,
sl->get_table_list(), &where, table_list, &where,
0)) != not_found_field) 0)) != not_found_field)
break; break;
if (sl->master_unit()->first_select()->linkage == if (sl->master_unit()->first_select()->linkage ==
......
...@@ -1000,7 +1000,7 @@ void st_select_lex::init_query() ...@@ -1000,7 +1000,7 @@ void st_select_lex::init_query()
item_list.empty(); item_list.empty();
join= 0; join= 0;
olap= UNSPECIFIED_OLAP_TYPE; olap= UNSPECIFIED_OLAP_TYPE;
having_fix_field= 0; insert_select= having_fix_field= 0;
with_wild= 0; with_wild= 0;
} }
......
...@@ -352,6 +352,14 @@ public: ...@@ -352,6 +352,14 @@ public:
bool braces; /* SELECT ... UNION (SELECT ... ) <- this braces */ bool braces; /* SELECT ... UNION (SELECT ... ) <- this braces */
/* TRUE when having fix field called in processing of this SELECT */ /* TRUE when having fix field called in processing of this SELECT */
bool having_fix_field; bool having_fix_field;
/*
TRUE for primary st_select_lex structure of simple INSERT/REPLACE
(used for name resolution, see Item_fiels & Item_ref fix_fields,
FALSE for INSERT/REPLACE ... SELECT, because it's
st_select_lex->table_list will be preprocessed (first table removed)
before passing to handle_select)
*/
bool insert_select;
void init_query(); void init_query();
void init_select(); void init_select();
......
...@@ -3270,6 +3270,7 @@ insert: ...@@ -3270,6 +3270,7 @@ insert:
lex->sql_command = SQLCOM_INSERT; lex->sql_command = SQLCOM_INSERT;
/* for subselects */ /* for subselects */
lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ; lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ;
lex->select_lex.insert_select= 1;
} insert_lock_option } insert_lock_option
opt_ignore insert2 opt_ignore insert2
{ {
...@@ -3285,6 +3286,7 @@ replace: ...@@ -3285,6 +3286,7 @@ replace:
LEX *lex=Lex; LEX *lex=Lex;
lex->sql_command = SQLCOM_REPLACE; lex->sql_command = SQLCOM_REPLACE;
lex->duplicates= DUP_REPLACE; lex->duplicates= DUP_REPLACE;
lex->select_lex.insert_select= 1;
} }
replace_lock_option insert2 replace_lock_option insert2
{ {
...@@ -3349,6 +3351,11 @@ insert_values: ...@@ -3349,6 +3351,11 @@ insert_values:
SQLCOM_INSERT_SELECT : SQLCOM_REPLACE_SELECT); SQLCOM_INSERT_SELECT : SQLCOM_REPLACE_SELECT);
lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ; lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ;
mysql_init_select(lex); mysql_init_select(lex);
/*
it is not simple select => table list will be
preprocessed before passing to handle_select
*/
lex->select_lex.insert_select= 0;
} }
select_options select_item_list opt_select_from select_lock_type select_options select_item_list opt_select_from select_lock_type
union_clause {} union_clause {}
......
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