summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/subselect.result8
-rw-r--r--mysql-test/t/subselect.test10
-rw-r--r--sql/item.cc19
-rw-r--r--sql/sql_lex.cc2
-rw-r--r--sql/sql_lex.h8
-rw-r--r--sql/sql_yacc.yy7
6 files changed, 45 insertions, 9 deletions
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index 1a4701d8d0e..c5ea027fed4 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -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);
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 8e8a3dfe1d4..5040f400514 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -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
diff --git a/sql/item.cc b/sql/item.cc
index 053a94cb695..871031f1571 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -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 ==
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 9bc4dfc74e7..6dc4b419f18 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -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;
}
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index f31b3305e07..5f6ae02cca3 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -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();
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 4de0e2f8c13..b62e34e279f 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -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 {}