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;
|
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
|
|||||||
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;
|
|||||||
#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;
|
|||||||
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
|
||||||
|
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
|
#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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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()
|
|||||||
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:
|
|||||||
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:
|
|||||||
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:
|
|||||||
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:
|
|||||||
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 {}
|
||||||
|
Reference in New Issue
Block a user