Commit 08d8bce5 authored by Igor Babaev's avatar Igor Babaev

MDEV-22786 Crashes with nested table value constructors

The bug caused crashes of the server when processing queries with nested
table value constructors (TVC) . It happened because the grammar rules to
parse TVC used the same global lists for both nested TVC and nesting TVC.
As a result invalid select trees were constructed for queries with nested
TVC and this led to crashes at the prepare stage.
This patch provides its own lists structures for each TVC nest level.

Besides the patch fixes a bug in the function wrap_tvc() that missed
inheritance of the SELECT_LEX::exclude_from_table_unique_test for
selects that wrapped TVCs. This inheritance is critical for specifications
of derived tables that employ nested TVCs.

Approved by dmitry.shulga@mariadb.com
parent 5bd994b0
......@@ -2887,4 +2887,179 @@ drop table t1,t2,t3;
select sum((values(1)));
sum((values(1)))
1
#
# MDEV-22786: Nested table values constructors
#
values ((values (2)));
(values (2))
2
values ((values (2)), (5), (select 4));
(values (2)) 5 (select 4)
2 5 4
values ((7), (values (2)), (5), (select 4));
7 (values (2)) 5 (select 4)
7 2 5 4
values ((values (2))) union values ((values (3)));
(values (2))
2
3
values ((values (2))), ((values (3)));
(values (2))
2
3
values ((values (2))), ((select 4)), ((values (3)));
(values (2))
2
4
3
values ((values (4)), (values (5))), ((values (1)), (values (7)));
(values (4)) (values (5))
4 5
1 7
values ((values (4)), (select 5)), ((select 1), (values (7)));
(values (4)) (select 5)
4 5
1 7
values ((select 2)) union values ((values (3)));
(select 2)
2
3
values ((values (2))) union values((select 3));
(values (2))
2
3
values ((values (2))) union all values ((values (2)));
(values (2))
2
2
values ((values (4)), (values (5))), ((values (1)), (values (7)))
union
values ((values (4)), (select 5)), ((select 2), (values (8)));
(values (4)) (values (5))
4 5
1 7
2 8
values ((values (4)), (values (5))), ((values (1)), (values (7)))
union all
values ((values (4)), (select 5)), ((select 2), (values (8)));
(values (4)) (values (5))
4 5
1 7
4 5
2 8
values ((values (1) union values (1)));
(values (1) union values (1))
1
values ((values (1) union values (1) union values (1)));
(values (1) union values (1) union values (1))
1
values ((values ((values (4)))));
(values ((values (4))))
4
values ((values ((select 5))));
(values ((select 5)))
5
values ((select (values (4))), (values ((values(5)))));
(select (values (4))) (values ((values(5))))
4 5
values ((select (values (4))), (values ((select 5))));
(select (values (4))) (values ((select 5)))
4 5
values ((select (values (4))), (values ((values(5)))))
union
values ((select (values (4))), (values ((select 7))));
(select (values (4))) (values ((values(5))))
4 5
4 7
values ((values (2))), ((values ((values (4)))));
(values (2))
2
4
values ((values (2))), ((values ((select 4))));
(values (2))
2
4
values ((values (2))), ((values ((values (4)))))
union
values ((values (8))), ((values ((select 4))));
(values (2))
2
4
8
values ((values (2))), ((values ((values (4)))))
union all
values ((values (8))), ((values ((select 4))));
(values (2))
2
4
8
4
select * from (values ((values (2)))) dt;
(values (2))
2
select * from (values ((values (2)), (5), (select 4))) dt;
(values (2)) 5 (select 4)
2 5 4
select * from (values ((values (2))) union values ((values (3)))) dt;
(values (2))
2
3
select * from (values ((values (2))), ((values (3)))) dt;
(values (2))
2
3
select * from (values ((values (2))), ((values (3)))) dt;
(values (2))
2
3
select * from (values ((values (2))), ((select 4)), ((values (3)))) dt;
(values (2))
2
4
3
create table t1 (a int);
insert into t1 values (3), (7), (1);
values ((values ((select a from t1 where a=7))));
(values ((select a from t1 where a=7)))
7
values ((values ((select (values(2)) from t1 where a=8))));
(values ((select (values(2)) from t1 where a=8)))
NULL
values ((values ((select a from t1 where a=7))))
union
values ((values ((select (values(2)) from t1 where a=8))));
(values ((select a from t1 where a=7)))
7
NULL
values ((values ((select a from t1 where a in ((values (7)))))));
(values ((select a from t1 where a in ((values (7))))))
7
values ((values ((select a from t1 where a in ((values (7), (8)))))));
(values ((select a from t1 where a in ((values (7), (8))))))
7
values ((values
((select a from t1 where a in (values (7) union values (8))))));
(values
((select a from t1 where a in (values (7) union values (8)))))
7
values ((values ((select (values(2)) from t1 where a=8))));
(values ((select (values(2)) from t1 where a=8)))
NULL
values ((select (values(2)) from t1 where a<7));
ERROR 21000: Subquery returns more than 1 row
select * from (values ((values ((select a from t1 where a=7))))) dt;
(values ((select a from t1 where a=7)))
7
select * from (values ((values ((select (values(2)) from t1 where a=8))))) dt;
(values ((select (values(2)) from t1 where a=8)))
NULL
insert into t1(a) values ((values (2))), ((values (3)));
select * from t1;
a
3
7
1
2
3
drop table t1;
End of 10.3 tests
......@@ -1522,4 +1522,110 @@ drop table t1,t2,t3;
select sum((values(1)));
--echo #
--echo # MDEV-22786: Nested table values constructors
--echo #
values ((values (2)));
values ((values (2)), (5), (select 4));
values ((7), (values (2)), (5), (select 4));
values ((values (2))) union values ((values (3)));
values ((values (2))), ((values (3)));
values ((values (2))), ((select 4)), ((values (3)));
values ((values (4)), (values (5))), ((values (1)), (values (7)));
values ((values (4)), (select 5)), ((select 1), (values (7)));
values ((select 2)) union values ((values (3)));
values ((values (2))) union values((select 3));
values ((values (2))) union all values ((values (2)));
values ((values (4)), (values (5))), ((values (1)), (values (7)))
union
values ((values (4)), (select 5)), ((select 2), (values (8)));
values ((values (4)), (values (5))), ((values (1)), (values (7)))
union all
values ((values (4)), (select 5)), ((select 2), (values (8)));
values ((values (1) union values (1)));
values ((values (1) union values (1) union values (1)));
values ((values ((values (4)))));
values ((values ((select 5))));
values ((select (values (4))), (values ((values(5)))));
values ((select (values (4))), (values ((select 5))));
values ((select (values (4))), (values ((values(5)))))
union
values ((select (values (4))), (values ((select 7))));
values ((values (2))), ((values ((values (4)))));
values ((values (2))), ((values ((select 4))));
values ((values (2))), ((values ((values (4)))))
union
values ((values (8))), ((values ((select 4))));
values ((values (2))), ((values ((values (4)))))
union all
values ((values (8))), ((values ((select 4))));
select * from (values ((values (2)))) dt;
select * from (values ((values (2)), (5), (select 4))) dt;
select * from (values ((values (2))) union values ((values (3)))) dt;
select * from (values ((values (2))), ((values (3)))) dt;
select * from (values ((values (2))), ((values (3)))) dt;
select * from (values ((values (2))), ((select 4)), ((values (3)))) dt;
create table t1 (a int);
insert into t1 values (3), (7), (1);
values ((values ((select a from t1 where a=7))));
values ((values ((select (values(2)) from t1 where a=8))));
values ((values ((select a from t1 where a=7))))
union
values ((values ((select (values(2)) from t1 where a=8))));
values ((values ((select a from t1 where a in ((values (7)))))));
values ((values ((select a from t1 where a in ((values (7), (8)))))));
values ((values
((select a from t1 where a in (values (7) union values (8))))));
values ((values ((select (values(2)) from t1 where a=8))));
--error ER_SUBQUERY_NO_1_ROW
values ((select (values(2)) from t1 where a<7));
select * from (values ((values ((select a from t1 where a=7))))) dt;
select * from (values ((values ((select (values(2)) from t1 where a=8))))) dt;
insert into t1(a) values ((values (2))), ((values (3)));
select * from t1;
drop table t1;
--echo End of 10.3 tests
......@@ -2421,6 +2421,8 @@ void st_select_lex::init_select()
with_dep= 0;
join= 0;
lock_type= TL_READ_DEFAULT;
save_many_values.empty();
save_insert_list= 0;
tvc= 0;
in_funcs.empty();
curr_tvc_name= 0;
......@@ -8302,16 +8304,52 @@ bool LEX::last_field_generated_always_as_row_end()
}
void LEX::save_values_list_state()
{
current_select->save_many_values= many_values;
current_select->save_insert_list= insert_list;
}
void LEX::restore_values_list_state()
{
many_values= current_select->save_many_values;
insert_list= current_select->save_insert_list;
}
void LEX::tvc_start()
{
if (current_select == &select_lex)
mysql_init_select(this);
else
save_values_list_state();
many_values.empty();
insert_list= 0;
}
bool LEX::tvc_start_derived()
{
if (current_select->linkage == GLOBAL_OPTIONS_TYPE ||
unlikely(mysql_new_select(this, 1, NULL)))
return true;
save_values_list_state();
many_values.empty();
insert_list= 0;
return false;
}
bool LEX::tvc_finalize()
{
mysql_init_select(this);
if (unlikely(!(current_select->tvc=
new (thd->mem_root)
table_value_constr(many_values,
current_select,
current_select->options))))
return true;
many_values.empty();
restore_values_list_state();
if (!current_select->master_unit()->fake_select_lex)
current_select->master_unit()->add_fake_select_lex(thd);
return false;
......@@ -8326,9 +8364,6 @@ bool LEX::tvc_finalize_derived()
thd->parse_error();
return true;
}
if (current_select->linkage == GLOBAL_OPTIONS_TYPE ||
unlikely(mysql_new_select(this, 1, NULL)))
return true;
current_select->linkage= DERIVED_TABLE_TYPE;
return tvc_finalize();
}
......
......@@ -1176,6 +1176,8 @@ class st_select_lex: public st_select_lex_node
/* it is for correct printing SELECT options */
thr_lock_type lock_type;
List<List_item> save_many_values;
List<Item> *save_insert_list;
table_value_constr *tvc;
bool in_tvc;
......@@ -4046,12 +4048,10 @@ struct LEX: public Query_tables_list
return false;
}
void tvc_start()
{
field_list.empty();
many_values.empty();
insert_list= 0;
}
void save_values_list_state();
void restore_values_list_state();
void tvc_start();
bool tvc_start_derived();
bool tvc_finalize();
bool tvc_finalize_derived();
......
......@@ -673,6 +673,8 @@ st_select_lex *wrap_tvc(THD *thd, st_select_lex *tvc_sl,
wrapper_sl->nest_level= tvc_sl->nest_level;
wrapper_sl->parsing_place= tvc_sl->parsing_place;
wrapper_sl->linkage= tvc_sl->linkage;
wrapper_sl->exclude_from_table_unique_test=
tvc_sl->exclude_from_table_unique_test;
lex->current_select= wrapper_sl;
item= new (thd->mem_root) Item_field(thd, &wrapper_sl->context,
......
......@@ -12334,7 +12334,8 @@ derived_query_specification:
derived_table_value_constructor:
VALUES
{
Lex->tvc_start();
if (Lex->tvc_start_derived())
MYSQL_YYABORT;
}
values_list
{
......
......@@ -12272,7 +12272,8 @@ derived_query_specification:
derived_table_value_constructor:
VALUES
{
Lex->tvc_start();
if (Lex->tvc_start_derived())
MYSQL_YYABORT;
}
values_list
{
......
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