Commit 26aeebfa authored by unknown's avatar unknown

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


mysql-test/r/subselect.result:
  subselect test changed
mysql-test/t/subselect.test:
  INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(x) FROM t2));
sql/item.cc:
  avoid resolving of INSER/REPLACE tables field in subqueries
sql/sql_lex.cc:
  Primary (top) simple INSERT/REPLACE st_select_lex indicator
sql/sql_lex.h:
  Primary (top) simple INSERT/REPLACE st_select_lex indicator
sql/sql_yacc.yy:
  Primary (top) simple INSERT/REPLACE st_select_lex indicator
parent 4637832f
......@@ -580,12 +580,12 @@ a b
drop table t11, t12, t2;
CREATE TABLE t1 (x int);
create table t2 (a int);
create table t3 (a int);
create table t3 (b int);
insert into t2 values (1);
insert into t3 values (1),(2);
INSERT INTO t1 (x) VALUES ((SELECT x FROM t1));
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
INSERT INTO t1 (x) VALUES ((SELECT a FROM t2));
select * from t1;
......@@ -607,13 +607,15 @@ x
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
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;
x
1
2
3
3
0
2
drop table t1, t2, t3;
CREATE TABLE t1 (x int not null, y int, primary key (x));
create table t2 (a int);
......
......@@ -334,13 +334,13 @@ drop table t11, t12, t2;
#insert with subselects
CREATE TABLE t1 (x int);
create table t2 (a int);
create table t3 (a int);
create table t3 (b int);
insert into t2 values (1);
insert into t3 values (1),(2);
-- error 1093
INSERT INTO t1 (x) VALUES ((SELECT x FROM t1));
-- 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));
select * from t1;
insert into t2 values (1);
......@@ -351,9 +351,15 @@ INSERT INTO t1 (x) select (SELECT SUM(a)+1 FROM t2) FROM t2;
select * from t1;
-- error 1093
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(a) FROM t2));
-- sleep 1
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;
#replace with subselects
......
......@@ -758,6 +758,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
#ifdef EMBEDDED_LIBRARY
thd->net.last_errno= 0;
#endif
TABLE_LIST *table_list;
Item **refer= (Item **)not_found_item;
uint counter;
// 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)
sl;
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,
(last= sl)->get_table_list(), &where,
table_list, &where,
0)) != not_found_field)
break;
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)
uint counter;
if (!ref)
{
TABLE_LIST *where= 0;
TABLE_LIST *where= 0, *table_list;
SELECT_LEX *sl= (outer_resolving?
thd->lex.current_select->select_lex():
thd->lex.current_select->outer_select());
......@@ -1260,8 +1267,14 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
REPORT_EXCEPT_NOT_FOUND)) !=
(Item **)not_found_item)
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,
sl->get_table_list(), &where,
table_list, &where,
0)) != not_found_field)
break;
if (sl->master_unit()->first_select()->linkage ==
......
......@@ -1000,7 +1000,7 @@ void st_select_lex::init_query()
item_list.empty();
join= 0;
olap= UNSPECIFIED_OLAP_TYPE;
having_fix_field= 0;
insert_select= having_fix_field= 0;
with_wild= 0;
}
......
......@@ -352,6 +352,14 @@ public:
bool braces; /* SELECT ... UNION (SELECT ... ) <- this braces */
/* TRUE when having fix field called in processing of this SELECT */
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_select();
......
......@@ -3270,6 +3270,7 @@ insert:
lex->sql_command = SQLCOM_INSERT;
/* for subselects */
lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ;
lex->select_lex.insert_select= 1;
} insert_lock_option
opt_ignore insert2
{
......@@ -3285,6 +3286,7 @@ replace:
LEX *lex=Lex;
lex->sql_command = SQLCOM_REPLACE;
lex->duplicates= DUP_REPLACE;
lex->select_lex.insert_select= 1;
}
replace_lock_option insert2
{
......@@ -3349,6 +3351,11 @@ insert_values:
SQLCOM_INSERT_SELECT : SQLCOM_REPLACE_SELECT);
lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ;
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
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