mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
fixed subqueries name resolution with INSERT/REPLACE (found during bug 446 investigation)
This commit is contained in:
@ -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
|
||||
|
19
sql/item.cc
19
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 ==
|
||||
|
@ -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 {}
|
||||
|
Reference in New Issue
Block a user