Commit 09aa5d3f authored by Igor Babaev's avatar Igor Babaev

MDEV-17894 Assertion `(thd->lex)->current_select' failed in MYSQLparse(),

           query with VALUES()

A table value constructor can be used in all contexts where a select
can be used. In particular an ORDER BY clause or a LIMIT clause or both
of them can be attached to a table value constructor to produce a new
query. Unfortunately execution of such queries was not supported.
This patch fixes the problem.
parent 9d805004
This diff is collapsed.
...@@ -1123,3 +1123,196 @@ PREPARE stmt FROM "SELECT * FROM (VALUES(1 + 1,2,'abc')) t"; ...@@ -1123,3 +1123,196 @@ PREPARE stmt FROM "SELECT * FROM (VALUES(1 + 1,2,'abc')) t";
EXECUTE stmt; EXECUTE stmt;
EXECUTE stmt; EXECUTE stmt;
DEALLOCATE PREPARE stmt; DEALLOCATE PREPARE stmt;
--echo #
--echo # MDEV-17894: tvc with ORDER BY ... LIMIT
--echo #
let $q=
values (5), (7), (1), (3), (4) limit 2;
eval $q;
eval explain extended $q;
let $q=
values (5), (7), (1), (3), (4) limit 2 offset 1;
eval $q;
eval explain extended $q;
let $q=
values (5), (7), (1), (3), (4) order by 1 limit 2;
eval $q;
eval explain extended $q;
let $q=
values (5), (7), (1), (3), (4) order by 1 limit 2 offset 1;
eval $q;
eval explain extended $q;
let $q=
values (5), (7), (1), (3), (4) order by 1;
eval $q;
eval explain extended $q;
let $q=
values (5,90), (7,20), (1,70), (3,50), (4,10) order by 2;
eval $q;
eval explain extended $q;
let $q=
select 2 union (values (5), (7), (1), (3), (4) limit 2);
eval $q;
eval explain extended $q;
let $q=
select 2 union (values (5), (7), (1), (3), (4) limit 2 offset 1);
eval $q;
eval explain extended $q;
let $q=
select 2 union (values (5), (7), (1), (3), (4) order by 1 limit 2);
eval $q;
eval explain extended $q;
let $q=
select 2 union (values (5), (7), (1), (3), (4) order by 1 limit 2 offset 1);
eval $q;
eval explain extended $q;
let $q=
(values (5), (7), (1), (3), (4) limit 2) union select 2;
eval $q;
eval explain extended $q;
let $q=
(values (5), (7), (1), (3), (4) limit 2 offset 1) union select 2;
eval $q;
eval explain extended $q;
let $q=
(values (5), (7), (1), (3), (4) order by 1 limit 2) union select 2;
eval $q;
eval explain extended $q;
let $q=
(values (5), (7), (1), (3), (4) order by 1 limit 2 offset 1) union select 2;
eval $q;
eval explain extended $q;
let $q=
select 3 union all (values (5), (7), (1), (3), (4) limit 2 offset 3);
eval $q;
eval explain extended $q;
let $q=
(values (5), (7), (1), (3), (4) limit 2 offset 3) union all select 3;
eval $q;
eval explain extended $q;
let $q=
select 3 union all (values (5), (7), (1), (3), (4) order by 1 limit 2);
eval $q;
eval explain extended $q;
let $q=
(values (5), (7), (1), (3), (4) order by 1 limit 2) union all select 3;
eval $q;
eval explain extended $q;
let $q=
( values (5), (7), (1), (3), (4) limit 2 offset 1 )
union
( values (5), (7), (1), (3), (4) order by 1 limit 2 );
eval $q;
eval explain extended $q;
let $q=
( values (5), (7), (1), (3), (4) limit 2 offset 1 )
union all
( values (5), (7), (1), (3), (4) order by 1 limit 2 );
eval $q;
eval explain extended $q;
let $q=
(values (5), (7), (1), (3), (4) limit 2 offset 3) union all select 3 order by 1;
eval $q;
eval explain extended $q;
let $q=
(values (5), (7), (1), (3), (4) order by 1 limit 3 offset 1) union all select 3 order by 1;
eval $q;
eval explain extended $q;
let $q=
(values (5), (7), (1), (3), (4) order by 1 limit 3 offset 1) union all select 3
order by 1 limit 2 offset 1;
eval $q;
eval explain extended $q;
--error ER_BAD_FIELD_ERROR
values (5,90), (7,20), (1,70), (3,50), (4,10) order by 3;
prepare stmt from "
select 2 union (values (5), (7), (1), (3), (4) limit 2)
";
execute stmt;
execute stmt;
deallocate prepare stmt;
prepare stmt from "
select 2 union (values (5), (7), (1), (3), (4) order by 1 limit 2)
";
execute stmt;
execute stmt;
deallocate prepare stmt;
prepare stmt from "
select 3 union all (values (5), (7), (1), (3), (4) limit 2)
";
execute stmt;
execute stmt;
deallocate prepare stmt;
prepare stmt from "
select 3 union all (values (5), (7), (1), (3), (4) order by 1 limit 2)
";
execute stmt;
execute stmt;
deallocate prepare stmt;
prepare stmt from "
( values (5), (7), (1), (3), (4) limit 2 offset 1 )
union
( values (5), (7), (1), (3), (4) order by 1 limit 2 );
";
execute stmt;
execute stmt;
deallocate prepare stmt;
--error ER_BAD_FIELD_ERROR
prepare stmt from "
values (5,90), (7,20), (1,70), (3,50), (4,10) order by 3;
";
create view v1 as values (5), (7), (1), (3), (4) order by 1 limit 2;
show create view v1;
select * from v1;
drop view v1;
create view v1 as
( values (5), (7), (1), (3), (4) limit 2 offset 1 )
union
( values (5), (7), (1), (3), (4) order by 1 limit 2 );
show create view v1;
select * from v1;
drop view v1;
--error ER_BAD_FIELD_ERROR
create view v1 as values (5,90), (7,20), (1,70), (3,50), (4,10) order by 3;
--error ER_BAD_FIELD_ERROR
create view v1 as
( values (5), (7), (1), (3), (4) limit 2 offset 1 )
union
( values (5), (7), (1), (3), (4) order by 2 limit 2 );
...@@ -1125,3 +1125,154 @@ DROP VIEW v1; ...@@ -1125,3 +1125,154 @@ DROP VIEW v1;
VALUES(1 + 1,2,'abc'); VALUES(1 + 1,2,'abc');
SELECT * FROM (VALUES(1 + 1,2,'abc')) t; SELECT * FROM (VALUES(1 + 1,2,'abc')) t;
--echo #
--echo # MDEV-17894: tvc with ORDER BY ... LIMIT
--echo #
let $q=
values (5), (7), (1), (3), (4) limit 2;
eval $q;
eval explain extended $q;
let $q=
values (5), (7), (1), (3), (4) limit 2 offset 1;
eval $q;
eval explain extended $q;
let $q=
values (5), (7), (1), (3), (4) order by 1 limit 2;
eval $q;
eval explain extended $q;
let $q=
values (5), (7), (1), (3), (4) order by 1 limit 2 offset 1;
eval $q;
eval explain extended $q;
let $q=
values (5), (7), (1), (3), (4) order by 1;
eval $q;
eval explain extended $q;
let $q=
values (5,90), (7,20), (1,70), (3,50), (4,10) order by 2;
eval $q;
eval explain extended $q;
let $q=
select 2 union (values (5), (7), (1), (3), (4) limit 2);
eval $q;
eval explain extended $q;
let $q=
select 2 union (values (5), (7), (1), (3), (4) limit 2 offset 1);
eval $q;
eval explain extended $q;
let $q=
select 2 union (values (5), (7), (1), (3), (4) order by 1 limit 2);
eval $q;
eval explain extended $q;
let $q=
select 2 union (values (5), (7), (1), (3), (4) order by 1 limit 2 offset 1);
eval $q;
eval explain extended $q;
let $q=
(values (5), (7), (1), (3), (4) limit 2) union select 2;
eval $q;
eval explain extended $q;
let $q=
(values (5), (7), (1), (3), (4) limit 2 offset 1) union select 2;
eval $q;
eval explain extended $q;
let $q=
(values (5), (7), (1), (3), (4) order by 1 limit 2) union select 2;
eval $q;
eval explain extended $q;
let $q=
(values (5), (7), (1), (3), (4) order by 1 limit 2 offset 1) union select 2;
eval $q;
eval explain extended $q;
let $q=
select 3 union all (values (5), (7), (1), (3), (4) limit 2 offset 3);
eval $q;
eval explain extended $q;
let $q=
(values (5), (7), (1), (3), (4) limit 2 offset 3) union all select 3;
eval $q;
eval explain extended $q;
let $q=
select 3 union all (values (5), (7), (1), (3), (4) order by 1 limit 2);
eval $q;
eval explain extended $q;
let $q=
(values (5), (7), (1), (3), (4) order by 1 limit 2) union all select 3;
eval $q;
eval explain extended $q;
let $q=
( values (5), (7), (1), (3), (4) limit 2 offset 1 )
union
( values (5), (7), (1), (3), (4) order by 1 limit 2 );
eval $q;
eval explain extended $q;
let $q=
( values (5), (7), (1), (3), (4) limit 2 offset 1 )
union all
( values (5), (7), (1), (3), (4) order by 1 limit 2 );
eval $q;
eval explain extended $q;
let $q=
(values (5), (7), (1), (3), (4) limit 2 offset 3) union all select 3 order by 1;
eval $q;
eval explain extended $q;
let $q=
(values (5), (7), (1), (3), (4) order by 1 limit 3 offset 1) union all select 3 order by 1;
eval $q;
eval explain extended $q;
let $q=
(values (5), (7), (1), (3), (4) order by 1 limit 3 offset 1) union all select 3
order by 1 limit 2 offset 1;
eval $q;
eval explain extended $q;
--error ER_BAD_FIELD_ERROR
values (5,90), (7,20), (1,70), (3,50), (4,10) order by 3;
create view v1 as values (5), (7), (1), (3), (4) order by 1 limit 2;
show create view v1;
select * from v1;
drop view v1;
create view v1 as
( values (5), (7), (1), (3), (4) limit 2 offset 1 )
union
( values (5), (7), (1), (3), (4) order by 1 limit 2 );
show create view v1;
select * from v1;
drop view v1;
--error ER_BAD_FIELD_ERROR
create view v1 as values (5,90), (7,20), (1,70), (3,50), (4,10) order by 3;
--error ER_BAD_FIELD_ERROR
create view v1 as
( values (5), (7), (1), (3), (4) limit 2 offset 1 )
union
( values (5), (7), (1), (3), (4) order by 2 limit 2 );
...@@ -269,7 +269,7 @@ bool Item_subselect::fix_fields(THD *thd_param, Item **ref) ...@@ -269,7 +269,7 @@ bool Item_subselect::fix_fields(THD *thd_param, Item **ref)
{ {
if (sl->tvc) if (sl->tvc)
{ {
wrap_tvc_in_derived_table(thd, sl); wrap_tvc_into_select(thd, sl);
} }
} }
......
...@@ -267,7 +267,7 @@ class Item_subselect :public Item_result_field, ...@@ -267,7 +267,7 @@ class Item_subselect :public Item_result_field,
Item* build_clone(THD *thd) { return 0; } Item* build_clone(THD *thd) { return 0; }
Item* get_copy(THD *thd) { return 0; } Item* get_copy(THD *thd) { return 0; }
bool wrap_tvc_in_derived_table(THD *thd, st_select_lex *tvc_sl); bool wrap_tvc_into_select(THD *thd, st_select_lex *tvc_sl);
friend class select_result_interceptor; friend class select_result_interceptor;
friend class Item_in_optimizer; friend class Item_in_optimizer;
......
...@@ -2292,6 +2292,7 @@ void st_select_lex_unit::init_query() ...@@ -2292,6 +2292,7 @@ void st_select_lex_unit::init_query()
with_element= 0; with_element= 0;
columns_are_renamed= false; columns_are_renamed= false;
intersect_mark= NULL; intersect_mark= NULL;
with_wrapped_tvc= false;
} }
void st_select_lex::init_query() void st_select_lex::init_query()
...@@ -3428,6 +3429,19 @@ bool st_select_lex_unit::union_needs_tmp_table() ...@@ -3428,6 +3429,19 @@ bool st_select_lex_unit::union_needs_tmp_table()
{ {
if (with_element && with_element->is_recursive) if (with_element && with_element->is_recursive)
return true; return true;
if (!with_wrapped_tvc)
{
for (st_select_lex *sl= first_select(); sl; sl=sl->next_select())
{
if (sl->tvc && sl->tvc->to_be_wrapped_as_with_tail())
{
with_wrapped_tvc= true;
break;
}
}
}
if (with_wrapped_tvc)
return true;
return union_distinct != NULL || return union_distinct != NULL ||
global_parameters()->order_list.elements != 0 || global_parameters()->order_list.elements != 0 ||
thd->lex->sql_command == SQLCOM_INSERT_SELECT || thd->lex->sql_command == SQLCOM_INSERT_SELECT ||
...@@ -8238,6 +8252,8 @@ bool LEX::tvc_finalize() ...@@ -8238,6 +8252,8 @@ bool LEX::tvc_finalize()
current_select->options)))) current_select->options))))
return true; return true;
many_values.empty(); many_values.empty();
if (!current_select->master_unit()->fake_select_lex)
current_select->master_unit()->add_fake_select_lex(thd);
return false; return false;
} }
......
...@@ -800,6 +800,12 @@ class st_select_lex_unit: public st_select_lex_node { ...@@ -800,6 +800,12 @@ class st_select_lex_unit: public st_select_lex_node {
table for it table for it
*/ */
Item_int *intersect_mark; Item_int *intersect_mark;
/**
TRUE if the unit contained TVC at the top level that has been wrapped
into SELECT:
VALUES (v1) ... (vn) => SELECT * FROM (VALUES (v1) ... (vn)) as tvc
*/
bool with_wrapped_tvc;
/** /**
Pointer to 'last' select, or pointer to select where we stored Pointer to 'last' select, or pointer to select where we stored
global parameters for union. global parameters for union.
......
This diff is collapsed.
...@@ -57,6 +57,8 @@ class table_value_constr : public Sql_alloc ...@@ -57,6 +57,8 @@ class table_value_constr : public Sql_alloc
select_result *tmp_result, select_result *tmp_result,
st_select_lex_unit *unit_arg); st_select_lex_unit *unit_arg);
bool to_be_wrapped_as_with_tail();
int save_explain_data_intern(THD *thd_arg, int save_explain_data_intern(THD *thd_arg,
Explain_query *output); Explain_query *output);
bool optimize(THD *thd_arg); bool optimize(THD *thd_arg);
...@@ -64,4 +66,7 @@ class table_value_constr : public Sql_alloc ...@@ -64,4 +66,7 @@ class table_value_constr : public Sql_alloc
void print(THD *thd_arg, String *str, enum_query_type query_type); void print(THD *thd_arg, String *str, enum_query_type query_type);
}; };
st_select_lex *wrap_tvc_with_tail(THD *thd, st_select_lex *tvc_sl);
#endif /* SQL_TVC_INCLUDED */ #endif /* SQL_TVC_INCLUDED */
...@@ -831,7 +831,8 @@ bool st_select_lex_unit::prepare(TABLE_LIST *derived_arg, ...@@ -831,7 +831,8 @@ bool st_select_lex_unit::prepare(TABLE_LIST *derived_arg,
bool is_union_select; bool is_union_select;
bool have_except= FALSE, have_intersect= FALSE; bool have_except= FALSE, have_intersect= FALSE;
bool instantiate_tmp_table= false; bool instantiate_tmp_table= false;
bool single_tvc= !first_sl->next_select() && first_sl->tvc; bool single_tvc= !first_sl->next_select() && first_sl->tvc &&
!fake_select_lex;
DBUG_ENTER("st_select_lex_unit::prepare"); DBUG_ENTER("st_select_lex_unit::prepare");
DBUG_ASSERT(thd == current_thd); DBUG_ASSERT(thd == current_thd);
...@@ -986,7 +987,23 @@ bool st_select_lex_unit::prepare(TABLE_LIST *derived_arg, ...@@ -986,7 +987,23 @@ bool st_select_lex_unit::prepare(TABLE_LIST *derived_arg,
{ {
if (sl->tvc) if (sl->tvc)
{ {
if (sl->tvc->prepare(thd, sl, tmp_result, this)) if (sl->tvc->to_be_wrapped_as_with_tail() &&
!(thd->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_VIEW))
{
st_select_lex *wrapper_sl= wrap_tvc_with_tail(thd, sl);
if (!wrapper_sl)
goto err;
if (sl == first_sl)
first_sl= wrapper_sl;
sl= wrapper_sl;
if (prepare_join(thd, sl, tmp_result, additional_options,
is_union_select))
goto err;
}
else if (sl->tvc->prepare(thd, sl, tmp_result, this))
goto err; goto err;
} }
else if (prepare_join(thd, sl, tmp_result, additional_options, else if (prepare_join(thd, sl, tmp_result, additional_options,
......
...@@ -9192,7 +9192,7 @@ select_paren: ...@@ -9192,7 +9192,7 @@ select_paren:
{ {
Lex->current_select->set_braces(true); Lex->current_select->set_braces(true);
} }
table_value_constructor table_value_constructor select_part3
{ {
DBUG_ASSERT(Lex->current_select->braces); DBUG_ASSERT(Lex->current_select->braces);
} }
...@@ -9212,6 +9212,12 @@ select_paren: ...@@ -9212,6 +9212,12 @@ select_paren:
| '(' select_paren ')' | '(' select_paren ')'
; ;
select_parent_union_query_term_proper:
SELECT_SYM select_options_and_item_list select_part3_union_query_term
opt_select_lock_type
| table_value_constructor select_part3_union_query_term
;
select_paren_union_query_term: select_paren_union_query_term:
{ {
/* /*
...@@ -9220,14 +9226,19 @@ select_paren_union_query_term: ...@@ -9220,14 +9226,19 @@ select_paren_union_query_term:
*/ */
Lex->current_select->set_braces(true); Lex->current_select->set_braces(true);
} }
SELECT_SYM select_options_and_item_list select_part3_union_query_term select_parent_union_query_term_proper
opt_select_lock_type
{ {
DBUG_ASSERT(Lex->current_select->braces); DBUG_ASSERT(Lex->current_select->braces);
} }
| '(' select_paren_union_query_term ')' | '(' select_paren_union_query_term ')'
; ;
select_parent_view_proper:
SELECT_SYM select_options_and_item_list select_part3_view
opt_select_lock_type
| table_value_constructor select_part3_view
;
select_paren_view: select_paren_view:
{ {
/* /*
...@@ -9236,8 +9247,7 @@ select_paren_view: ...@@ -9236,8 +9247,7 @@ select_paren_view:
*/ */
Lex->current_select->set_braces(true); Lex->current_select->set_braces(true);
} }
SELECT_SYM select_options_and_item_list select_part3_view select_parent_view_proper
opt_select_lock_type
{ {
DBUG_ASSERT(Lex->current_select->braces); DBUG_ASSERT(Lex->current_select->braces);
} }
......
...@@ -9129,7 +9129,7 @@ select_paren: ...@@ -9129,7 +9129,7 @@ select_paren:
{ {
Lex->current_select->set_braces(true); Lex->current_select->set_braces(true);
} }
table_value_constructor table_value_constructor select_part3
{ {
DBUG_ASSERT(Lex->current_select->braces); DBUG_ASSERT(Lex->current_select->braces);
} }
...@@ -9149,6 +9149,12 @@ select_paren: ...@@ -9149,6 +9149,12 @@ select_paren:
| '(' select_paren ')' | '(' select_paren ')'
; ;
select_parent_union_query_term_proper:
SELECT_SYM select_options_and_item_list select_part3_union_query_term
opt_select_lock_type
| table_value_constructor select_part3_union_query_term
;
select_paren_union_query_term: select_paren_union_query_term:
{ {
/* /*
...@@ -9157,14 +9163,19 @@ select_paren_union_query_term: ...@@ -9157,14 +9163,19 @@ select_paren_union_query_term:
*/ */
Lex->current_select->set_braces(true); Lex->current_select->set_braces(true);
} }
SELECT_SYM select_options_and_item_list select_part3_union_query_term select_parent_union_query_term_proper
opt_select_lock_type
{ {
DBUG_ASSERT(Lex->current_select->braces); DBUG_ASSERT(Lex->current_select->braces);
} }
| '(' select_paren_union_query_term ')' | '(' select_paren_union_query_term ')'
; ;
select_parent_view_proper:
SELECT_SYM select_options_and_item_list select_part3_view
opt_select_lock_type
| table_value_constructor select_part3_view
;
select_paren_view: select_paren_view:
{ {
/* /*
...@@ -9173,8 +9184,7 @@ select_paren_view: ...@@ -9173,8 +9184,7 @@ select_paren_view:
*/ */
Lex->current_select->set_braces(true); Lex->current_select->set_braces(true);
} }
SELECT_SYM select_options_and_item_list select_part3_view select_parent_view_proper
opt_select_lock_type
{ {
DBUG_ASSERT(Lex->current_select->braces); DBUG_ASSERT(Lex->current_select->braces);
} }
......
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