Commit f988bcec authored by Oleksandr Byelkin's avatar Oleksandr Byelkin

MDEV-10776: Server crash on query

Exclude untouched in prepare phese subqueries from the select/unit tree
because they became unreachable by execution.
parent 46dee0d1
...@@ -7094,3 +7094,14 @@ a ...@@ -7094,3 +7094,14 @@ a
0 0
DROP TABLE t1; DROP TABLE t1;
SET SESSION big_tables=0; SET SESSION big_tables=0;
#
# MDEV-10776: Server crash on query
#
create table t1 (field1 int);
insert into t1 values (1);
select round((select 1 from t1 limit 1))
from t1
group by round((select 1 from t1 limit 1));
round((select 1 from t1 limit 1))
1
drop table t1;
...@@ -7091,6 +7091,17 @@ a ...@@ -7091,6 +7091,17 @@ a
0 0
DROP TABLE t1; DROP TABLE t1;
SET SESSION big_tables=0; SET SESSION big_tables=0;
#
# MDEV-10776: Server crash on query
#
create table t1 (field1 int);
insert into t1 values (1);
select round((select 1 from t1 limit 1))
from t1
group by round((select 1 from t1 limit 1));
round((select 1 from t1 limit 1))
1
drop table t1;
set optimizer_switch=default; set optimizer_switch=default;
select @@optimizer_switch like '%materialization=on%'; select @@optimizer_switch like '%materialization=on%';
@@optimizer_switch like '%materialization=on%' @@optimizer_switch like '%materialization=on%'
......
...@@ -7089,4 +7089,15 @@ a ...@@ -7089,4 +7089,15 @@ a
0 0
DROP TABLE t1; DROP TABLE t1;
SET SESSION big_tables=0; SET SESSION big_tables=0;
#
# MDEV-10776: Server crash on query
#
create table t1 (field1 int);
insert into t1 values (1);
select round((select 1 from t1 limit 1))
from t1
group by round((select 1 from t1 limit 1));
round((select 1 from t1 limit 1))
1
drop table t1;
set @optimizer_switch_for_subselect_test=null; set @optimizer_switch_for_subselect_test=null;
...@@ -7100,6 +7100,17 @@ a ...@@ -7100,6 +7100,17 @@ a
0 0
DROP TABLE t1; DROP TABLE t1;
SET SESSION big_tables=0; SET SESSION big_tables=0;
#
# MDEV-10776: Server crash on query
#
create table t1 (field1 int);
insert into t1 values (1);
select round((select 1 from t1 limit 1))
from t1
group by round((select 1 from t1 limit 1));
round((select 1 from t1 limit 1))
1
drop table t1;
set optimizer_switch=default; set optimizer_switch=default;
select @@optimizer_switch like '%subquery_cache=on%'; select @@optimizer_switch like '%subquery_cache=on%';
@@optimizer_switch like '%subquery_cache=on%' @@optimizer_switch like '%subquery_cache=on%'
......
...@@ -7089,5 +7089,16 @@ a ...@@ -7089,5 +7089,16 @@ a
0 0
DROP TABLE t1; DROP TABLE t1;
SET SESSION big_tables=0; SET SESSION big_tables=0;
#
# MDEV-10776: Server crash on query
#
create table t1 (field1 int);
insert into t1 values (1);
select round((select 1 from t1 limit 1))
from t1
group by round((select 1 from t1 limit 1));
round((select 1 from t1 limit 1))
1
drop table t1;
set @optimizer_switch_for_subselect_test=null; set @optimizer_switch_for_subselect_test=null;
set @join_cache_level_for_subselect_test=NULL; set @join_cache_level_for_subselect_test=NULL;
...@@ -5974,3 +5974,17 @@ INSERT INTO t1 VALUES(0),(0),(0); ...@@ -5974,3 +5974,17 @@ INSERT INTO t1 VALUES(0),(0),(0);
SELECT * FROM t1 WHERE a IN(SELECT MIN(a) FROM t1); SELECT * FROM t1 WHERE a IN(SELECT MIN(a) FROM t1);
DROP TABLE t1; DROP TABLE t1;
SET SESSION big_tables=0; SET SESSION big_tables=0;
--echo #
--echo # MDEV-10776: Server crash on query
--echo #
create table t1 (field1 int);
insert into t1 values (1);
select round((select 1 from t1 limit 1))
from t1
group by round((select 1 from t1 limit 1));
drop table t1;
...@@ -209,6 +209,7 @@ bool ...@@ -209,6 +209,7 @@ bool
Item_subselect::select_transformer(JOIN *join) Item_subselect::select_transformer(JOIN *join)
{ {
DBUG_ENTER("Item_subselect::select_transformer"); DBUG_ENTER("Item_subselect::select_transformer");
DBUG_ASSERT(thd == join->thd);
DBUG_RETURN(false); DBUG_RETURN(false);
} }
...@@ -579,7 +580,7 @@ bool Item_subselect::is_expensive() ...@@ -579,7 +580,7 @@ bool Item_subselect::is_expensive()
examined_rows+= cur_join->get_examined_rows(); examined_rows+= cur_join->get_examined_rows();
} }
// here we are sure that subquery is optimized so thd is set
return (examined_rows > thd->variables.expensive_subquery_limit); return (examined_rows > thd->variables.expensive_subquery_limit);
} }
...@@ -643,6 +644,7 @@ bool Item_subselect::exec() ...@@ -643,6 +644,7 @@ bool Item_subselect::exec()
subselect_engine *org_engine= engine; subselect_engine *org_engine= engine;
DBUG_ENTER("Item_subselect::exec"); DBUG_ENTER("Item_subselect::exec");
DBUG_ASSERT(fixed);
/* /*
Do not execute subselect in case of a fatal error Do not execute subselect in case of a fatal error
...@@ -688,6 +690,7 @@ int Item_in_subselect::optimize(double *out_rows, double *cost) ...@@ -688,6 +690,7 @@ int Item_in_subselect::optimize(double *out_rows, double *cost)
{ {
int res; int res;
DBUG_ENTER("Item_in_subselect::optimize"); DBUG_ENTER("Item_in_subselect::optimize");
DBUG_ASSERT(fixed);
SELECT_LEX *save_select= thd->lex->current_select; SELECT_LEX *save_select= thd->lex->current_select;
JOIN *join= unit->first_select()->join; JOIN *join= unit->first_select()->join;
...@@ -802,6 +805,7 @@ bool Item_in_subselect::expr_cache_is_needed(THD *thd) ...@@ -802,6 +805,7 @@ bool Item_in_subselect::expr_cache_is_needed(THD *thd)
bool Item_in_subselect::exec() bool Item_in_subselect::exec()
{ {
DBUG_ENTER("Item_in_subselect::exec"); DBUG_ENTER("Item_in_subselect::exec");
DBUG_ASSERT(fixed);
/* /*
Initialize the cache of the left predicate operand. This has to be done as Initialize the cache of the left predicate operand. This has to be done as
late as now, because Cached_item directly contains a resolved field (not late as now, because Cached_item directly contains a resolved field (not
...@@ -856,6 +860,7 @@ table_map Item_subselect::used_tables() const ...@@ -856,6 +860,7 @@ table_map Item_subselect::used_tables() const
bool Item_subselect::const_item() const bool Item_subselect::const_item() const
{ {
DBUG_ASSERT(thd);
return (thd->lex->context_analysis_only ? return (thd->lex->context_analysis_only ?
FALSE : FALSE :
forced_const || const_item_cache); forced_const || const_item_cache);
...@@ -1049,10 +1054,11 @@ Item_singlerow_subselect::select_transformer(JOIN *join) ...@@ -1049,10 +1054,11 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
DBUG_ENTER("Item_singlerow_subselect::select_transformer"); DBUG_ENTER("Item_singlerow_subselect::select_transformer");
if (changed) if (changed)
DBUG_RETURN(false); DBUG_RETURN(false);
DBUG_ASSERT(join->thd == thd);
SELECT_LEX *select_lex= join->select_lex; SELECT_LEX *select_lex= join->select_lex;
Query_arena *arena= thd->stmt_arena; Query_arena *arena= thd->stmt_arena;
if (!select_lex->master_unit()->is_union() && if (!select_lex->master_unit()->is_union() &&
!select_lex->table_list.elements && !select_lex->table_list.elements &&
select_lex->item_list.elements == 1 && select_lex->item_list.elements == 1 &&
...@@ -1717,6 +1723,7 @@ Item_in_subselect::single_value_transformer(JOIN *join) ...@@ -1717,6 +1723,7 @@ Item_in_subselect::single_value_transformer(JOIN *join)
{ {
SELECT_LEX *select_lex= join->select_lex; SELECT_LEX *select_lex= join->select_lex;
DBUG_ENTER("Item_in_subselect::single_value_transformer"); DBUG_ENTER("Item_in_subselect::single_value_transformer");
DBUG_ASSERT(thd == join->thd);
/* /*
Check that the right part of the subselect contains no more than one Check that the right part of the subselect contains no more than one
...@@ -1829,9 +1836,9 @@ bool Item_allany_subselect::transform_into_max_min(JOIN *join) ...@@ -1829,9 +1836,9 @@ bool Item_allany_subselect::transform_into_max_min(JOIN *join)
if (!test_strategy(SUBS_MAXMIN_INJECTED | SUBS_MAXMIN_ENGINE)) if (!test_strategy(SUBS_MAXMIN_INJECTED | SUBS_MAXMIN_ENGINE))
DBUG_RETURN(false); DBUG_RETURN(false);
Item **place= optimizer->arguments() + 1; Item **place= optimizer->arguments() + 1;
THD *thd= join->thd;
SELECT_LEX *select_lex= join->select_lex; SELECT_LEX *select_lex= join->select_lex;
Item *subs; Item *subs;
DBUG_ASSERT(thd == join->thd);
/* /*
*/ */
...@@ -1938,6 +1945,7 @@ bool Item_allany_subselect::transform_into_max_min(JOIN *join) ...@@ -1938,6 +1945,7 @@ bool Item_allany_subselect::transform_into_max_min(JOIN *join)
bool Item_in_subselect::fix_having(Item *having, SELECT_LEX *select_lex) bool Item_in_subselect::fix_having(Item *having, SELECT_LEX *select_lex)
{ {
bool fix_res= 0; bool fix_res= 0;
DBUG_ASSERT(thd);
if (!having->fixed) if (!having->fixed)
{ {
select_lex->having_fix_field= 1; select_lex->having_fix_field= 1;
...@@ -2000,6 +2008,7 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join, ...@@ -2000,6 +2008,7 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join,
Item **having_item) Item **having_item)
{ {
SELECT_LEX *select_lex= join->select_lex; SELECT_LEX *select_lex= join->select_lex;
DBUG_ASSERT(thd == join->thd);
/* /*
The non-transformed HAVING clause of 'join' may be stored in two ways The non-transformed HAVING clause of 'join' may be stored in two ways
during JOIN::optimize: this->tmp_having= this->having; this->having= 0; during JOIN::optimize: this->tmp_having= this->having; this->having= 0;
...@@ -2136,6 +2145,7 @@ Item_in_subselect::row_value_transformer(JOIN *join) ...@@ -2136,6 +2145,7 @@ Item_in_subselect::row_value_transformer(JOIN *join)
uint cols_num= left_expr->cols(); uint cols_num= left_expr->cols();
DBUG_ENTER("Item_in_subselect::row_value_transformer"); DBUG_ENTER("Item_in_subselect::row_value_transformer");
DBUG_ASSERT(thd == join->thd);
// psergey: duplicated_subselect_card_check // psergey: duplicated_subselect_card_check
if (select_lex->item_list.elements != cols_num) if (select_lex->item_list.elements != cols_num)
...@@ -2248,6 +2258,7 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join, ...@@ -2248,6 +2258,7 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join,
!select_lex->table_list.elements); !select_lex->table_list.elements);
DBUG_ENTER("Item_in_subselect::create_row_in_to_exists_cond"); DBUG_ENTER("Item_in_subselect::create_row_in_to_exists_cond");
DBUG_ASSERT(thd == join->thd);
*where_item= NULL; *where_item= NULL;
*having_item= NULL; *having_item= NULL;
...@@ -2473,6 +2484,7 @@ bool Item_in_subselect::inject_in_to_exists_cond(JOIN *join_arg) ...@@ -2473,6 +2484,7 @@ bool Item_in_subselect::inject_in_to_exists_cond(JOIN *join_arg)
Item *having_item= join_arg->in_to_exists_having; Item *having_item= join_arg->in_to_exists_having;
DBUG_ENTER("Item_in_subselect::inject_in_to_exists_cond"); DBUG_ENTER("Item_in_subselect::inject_in_to_exists_cond");
DBUG_ASSERT(thd == join_arg->thd);
if (where_item) if (where_item)
{ {
...@@ -2561,6 +2573,7 @@ Item_in_subselect::select_in_like_transformer(JOIN *join) ...@@ -2561,6 +2573,7 @@ Item_in_subselect::select_in_like_transformer(JOIN *join)
bool result; bool result;
DBUG_ENTER("Item_in_subselect::select_in_like_transformer"); DBUG_ENTER("Item_in_subselect::select_in_like_transformer");
DBUG_ASSERT(thd == join->thd);
/* /*
IN/SOME/ALL/ANY subqueries aren't support LIMIT clause. Without it IN/SOME/ALL/ANY subqueries aren't support LIMIT clause. Without it
...@@ -2762,6 +2775,7 @@ bool Item_in_subselect::setup_mat_engine() ...@@ -2762,6 +2775,7 @@ bool Item_in_subselect::setup_mat_engine()
subselect_single_select_engine *select_engine; subselect_single_select_engine *select_engine;
DBUG_ENTER("Item_in_subselect::setup_mat_engine"); DBUG_ENTER("Item_in_subselect::setup_mat_engine");
DBUG_ASSERT(thd);
/* /*
The select_engine (that executes transformed IN=>EXISTS subselects) is The select_engine (that executes transformed IN=>EXISTS subselects) is
...@@ -2800,6 +2814,7 @@ bool Item_in_subselect::setup_mat_engine() ...@@ -2800,6 +2814,7 @@ bool Item_in_subselect::setup_mat_engine()
bool Item_in_subselect::init_left_expr_cache() bool Item_in_subselect::init_left_expr_cache()
{ {
JOIN *outer_join; JOIN *outer_join;
DBUG_ASSERT(thd);
outer_join= unit->outer_select()->join; outer_join= unit->outer_select()->join;
/* /*
...@@ -2826,6 +2841,7 @@ bool Item_in_subselect::init_left_expr_cache() ...@@ -2826,6 +2841,7 @@ bool Item_in_subselect::init_left_expr_cache()
bool Item_in_subselect::init_cond_guards() bool Item_in_subselect::init_cond_guards()
{ {
DBUG_ASSERT(thd);
uint cols_num= left_expr->cols(); uint cols_num= left_expr->cols();
if (!abort_on_null && left_expr->maybe_null && !pushed_cond_guards) if (!abort_on_null && left_expr->maybe_null && !pushed_cond_guards)
{ {
......
...@@ -3486,12 +3486,28 @@ bool st_select_lex::add_index_hint (THD *thd, char *str, uint length) ...@@ -3486,12 +3486,28 @@ bool st_select_lex::add_index_hint (THD *thd, char *str, uint length)
bool st_select_lex::optimize_unflattened_subqueries(bool const_only) bool st_select_lex::optimize_unflattened_subqueries(bool const_only)
{ {
for (SELECT_LEX_UNIT *un= first_inner_unit(); un; un= un->next_unit()) SELECT_LEX_UNIT *next_unit= NULL;
for (SELECT_LEX_UNIT *un= first_inner_unit();
un;
un= next_unit ? next_unit : un->next_unit())
{ {
Item_subselect *subquery_predicate= un->item; Item_subselect *subquery_predicate= un->item;
next_unit= NULL;
if (subquery_predicate) if (subquery_predicate)
{ {
if (!subquery_predicate->fixed)
{
/*
This subquery was excluded as part of some expression so it is
invisible from all prepared expression.
*/
next_unit= un->next_unit();
un->exclude_level();
if (next_unit)
continue;
break;
}
if (subquery_predicate->substype() == Item_subselect::IN_SUBS) if (subquery_predicate->substype() == Item_subselect::IN_SUBS)
{ {
Item_in_subselect *in_subs= (Item_in_subselect*) subquery_predicate; Item_in_subselect *in_subs= (Item_in_subselect*) subquery_predicate;
......
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