mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
MDEV-19956 Queries with subqueries containing UNION are not parsed
Shift-Reduce conflicts prevented parsing some queries with subqueries that used set operations when the subqueries occurred in expressions or in IN predicands. The grammar rules for query expression were transformed in order to avoid these conflicts. New grammar rules employ an idea taken from MySQL 8.0.
This commit is contained in:
@ -831,8 +831,8 @@ bool st_select_lex_unit::prepare(TABLE_LIST *derived_arg,
|
||||
bool is_union_select;
|
||||
bool have_except= FALSE, have_intersect= FALSE;
|
||||
bool instantiate_tmp_table= false;
|
||||
bool single_tvc= !first_sl->next_select() && first_sl->tvc &&
|
||||
!fake_select_lex;
|
||||
bool single_tvc= !first_sl->next_select() && first_sl->tvc;
|
||||
bool single_tvc_wo_order= single_tvc && !first_sl->order_list.elements;
|
||||
DBUG_ENTER("st_select_lex_unit::prepare");
|
||||
DBUG_ASSERT(thd == current_thd);
|
||||
|
||||
@ -924,8 +924,9 @@ bool st_select_lex_unit::prepare(TABLE_LIST *derived_arg,
|
||||
|
||||
if (is_union_select || is_recursive)
|
||||
{
|
||||
if ((is_unit_op() && !union_needs_tmp_table() &&
|
||||
!have_except && !have_intersect) || single_tvc)
|
||||
if ((single_tvc_wo_order && !fake_select_lex) ||
|
||||
(is_unit_op() && !union_needs_tmp_table() &&
|
||||
!have_except && !have_intersect && !single_tvc))
|
||||
{
|
||||
SELECT_LEX *last= first_select();
|
||||
while (last->next_select())
|
||||
@ -940,7 +941,7 @@ bool st_select_lex_unit::prepare(TABLE_LIST *derived_arg,
|
||||
else
|
||||
{
|
||||
if (!is_recursive)
|
||||
union_result= new (thd->mem_root) select_unit(thd);
|
||||
union_result= new (thd->mem_root) select_unit(thd);
|
||||
else
|
||||
{
|
||||
with_element->rec_result=
|
||||
@ -986,17 +987,40 @@ bool st_select_lex_unit::prepare(TABLE_LIST *derived_arg,
|
||||
if (sl->tvc && sl->order_list.elements &&
|
||||
!sl->tvc->to_be_wrapped_as_with_tail())
|
||||
{
|
||||
SELECT_LEX_UNIT *unit= sl->master_unit();
|
||||
if (thd->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_VIEW)
|
||||
{
|
||||
sl->master_unit()->fake_select_lex= 0;
|
||||
sl->master_unit()->saved_fake_select_lex= 0;
|
||||
unit->fake_select_lex= 0;
|
||||
unit->saved_fake_select_lex= 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sl->order_list.empty();
|
||||
sl->explicit_limit= 0;
|
||||
sl->select_limit= 0;
|
||||
sl->offset_limit= 0;
|
||||
if (!unit->first_select()->next_select())
|
||||
{
|
||||
if (!unit->fake_select_lex)
|
||||
{
|
||||
Query_arena *arena, backup_arena;
|
||||
arena= thd->activate_stmt_arena_if_needed(&backup_arena);
|
||||
bool rc= unit->add_fake_select_lex(thd);
|
||||
if (arena)
|
||||
thd->restore_active_arena(arena, &backup_arena);
|
||||
if (rc)
|
||||
goto err;
|
||||
}
|
||||
SELECT_LEX *fake= unit->fake_select_lex;
|
||||
fake->order_list= sl->order_list;
|
||||
fake->explicit_limit= sl->explicit_limit;
|
||||
fake->select_limit= sl->select_limit;
|
||||
fake->offset_limit= sl->offset_limit;
|
||||
sl->order_list.empty();
|
||||
sl->explicit_limit= 0;
|
||||
sl->select_limit= 0;
|
||||
sl->offset_limit= 0;
|
||||
if (describe)
|
||||
fake->options|= SELECT_DESCRIBE;
|
||||
}
|
||||
else if (!sl->explicit_limit)
|
||||
sl->order_list.empty();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1021,7 +1045,7 @@ bool st_select_lex_unit::prepare(TABLE_LIST *derived_arg,
|
||||
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,
|
||||
is_union_select))
|
||||
|
Reference in New Issue
Block a user