diff --git a/mysql-test/main/table_value_constr.result b/mysql-test/main/table_value_constr.result index d2965ab1f6c..ff6d19a8e0e 100644 --- a/mysql-test/main/table_value_constr.result +++ b/mysql-test/main/table_value_constr.result @@ -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 diff --git a/mysql-test/main/table_value_constr.test b/mysql-test/main/table_value_constr.test index 88d0ac2fbbf..3e976f88ed5 100644 --- a/mysql-test/main/table_value_constr.test +++ b/mysql-test/main/table_value_constr.test @@ -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 diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 70d795c145d..c2bc8386404 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -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(); } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 979e212c1f6..474f3174ac9 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1176,6 +1176,8 @@ public: /* it is for correct printing SELECT options */ thr_lock_type lock_type; + List save_many_values; + List *save_insert_list; table_value_constr *tvc; bool in_tvc; @@ -4046,12 +4048,10 @@ public: 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(); diff --git a/sql/sql_tvc.cc b/sql/sql_tvc.cc index cb056b0e15f..96c5223ee6a 100644 --- a/sql/sql_tvc.cc +++ b/sql/sql_tvc.cc @@ -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, diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 88f12e97bfa..b26e2ddbf1b 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -12334,7 +12334,8 @@ derived_query_specification: derived_table_value_constructor: VALUES { - Lex->tvc_start(); + if (Lex->tvc_start_derived()) + MYSQL_YYABORT; } values_list { diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy index eaeaf2e5e7e..4af034db921 100644 --- a/sql/sql_yacc_ora.yy +++ b/sql/sql_yacc_ora.yy @@ -12272,7 +12272,8 @@ derived_query_specification: derived_table_value_constructor: VALUES { - Lex->tvc_start(); + if (Lex->tvc_start_derived()) + MYSQL_YYABORT; } values_list {