Skip to content

Commit

Permalink
MDEV-7911: crash in Item_cond::eval_not_null_tables
Browse files Browse the repository at this point in the history
convert_subq_to_sj() must check the results of in_equality->fix_fields()
call. It can fail in a meaningful way when e.g. we're trying to compare
columns with incompatible collations.
  • Loading branch information
spetrunia committed Apr 21, 2015
1 parent f1f8adf commit e428c80
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 9 deletions.
9 changes: 9 additions & 0 deletions mysql-test/r/subselect_sj.result
Original file line number Diff line number Diff line change
Expand Up @@ -2986,4 +2986,13 @@ pk1 i1 i2 c2 pk3 i3 c3
SET join_cache_level=@tmp_mdev5059;
set optimizer_switch=@tmp_os_mdev5059;
DROP TABLE t1,t2,t3,t4;
#
# MDEV-7911: crash in Item_cond::eval_not_null_tables
#
create table t1(a int);
insert into t1 values(1),(2),(3),(null);
explain
select 1 from t1 where _cp932 "1" in (select '1' from t1);
ERROR HY000: Illegal mix of collations (cp932_japanese_ci,COERCIBLE) and (latin1_swedish_ci,COERCIBLE) for operation '='
drop table t1;
set optimizer_switch=@subselect_sj_tmp;
9 changes: 9 additions & 0 deletions mysql-test/r/subselect_sj_jcl6.result
Original file line number Diff line number Diff line change
Expand Up @@ -3000,6 +3000,15 @@ pk1 i1 i2 c2 pk3 i3 c3
SET join_cache_level=@tmp_mdev5059;
set optimizer_switch=@tmp_os_mdev5059;
DROP TABLE t1,t2,t3,t4;
#
# MDEV-7911: crash in Item_cond::eval_not_null_tables
#
create table t1(a int);
insert into t1 values(1),(2),(3),(null);
explain
select 1 from t1 where _cp932 "1" in (select '1' from t1);
ERROR HY000: Illegal mix of collations (cp932_japanese_ci,COERCIBLE) and (latin1_swedish_ci,COERCIBLE) for operation '='
drop table t1;
set optimizer_switch=@subselect_sj_tmp;
#
# BUG#49129: Wrong result with IN-subquery with join_cache_level=6 and firstmatch=off
Expand Down
11 changes: 11 additions & 0 deletions mysql-test/t/subselect_sj.test
Original file line number Diff line number Diff line change
Expand Up @@ -2689,5 +2689,16 @@ SET join_cache_level=@tmp_mdev5059;
set optimizer_switch=@tmp_os_mdev5059;
DROP TABLE t1,t2,t3,t4;

--echo #
--echo # MDEV-7911: crash in Item_cond::eval_not_null_tables
--echo #

create table t1(a int);
insert into t1 values(1),(2),(3),(null);
--error ER_CANT_AGGREGATE_2COLLATIONS
explain
select 1 from t1 where _cp932 "1" in (select '1' from t1);
drop table t1;

# The following command must be the last one the file
set optimizer_switch=@subselect_sj_tmp;
36 changes: 27 additions & 9 deletions sql/opt_subselect.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1610,9 +1610,20 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
sj_nest->sj_on_expr= and_items(sj_nest->sj_on_expr, item_eq);
}
}
/* Fix the created equality and AND */
if (!sj_nest->sj_on_expr->fixed)
sj_nest->sj_on_expr->fix_fields(parent_join->thd, &sj_nest->sj_on_expr);
/*
Fix the created equality and AND
Note that fix_fields() can actually fail in a meaningful way here. One
example is when the IN-equality is not valid, because it compares columns
with incompatible collations. (One can argue it would be more appropriate
to check for this at name resolution stage, but as a legacy of IN->EXISTS
we have in here).
*/
if (!sj_nest->sj_on_expr->fixed &&
sj_nest->sj_on_expr->fix_fields(parent_join->thd, &sj_nest->sj_on_expr))
{
DBUG_RETURN(TRUE);
}

/*
Walk through sj nest's WHERE and ON expressions and call
Expand All @@ -1631,12 +1642,15 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
/* Inject sj_on_expr into the parent's WHERE or ON */
if (emb_tbl_nest)
{
emb_tbl_nest->on_expr= and_items(emb_tbl_nest->on_expr,
emb_tbl_nest->on_expr= and_items(emb_tbl_nest->on_expr,
sj_nest->sj_on_expr);
emb_tbl_nest->on_expr->top_level_item();
if (!emb_tbl_nest->on_expr->fixed)
emb_tbl_nest->on_expr->fix_fields(parent_join->thd,
&emb_tbl_nest->on_expr);
if (!emb_tbl_nest->on_expr->fixed &&
emb_tbl_nest->on_expr->fix_fields(parent_join->thd,
&emb_tbl_nest->on_expr))
{
DBUG_RETURN(TRUE);
}
}
else
{
Expand All @@ -1649,8 +1663,12 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
*/
save_lex= thd->lex->current_select;
thd->lex->current_select=parent_join->select_lex;
if (!parent_join->conds->fixed)
parent_join->conds->fix_fields(parent_join->thd, &parent_join->conds);
if (!parent_join->conds->fixed &&
parent_join->conds->fix_fields(parent_join->thd,
&parent_join->conds))
{
DBUG_RETURN(1);
}
thd->lex->current_select=save_lex;
parent_join->select_lex->where= parent_join->conds;
}
Expand Down

0 comments on commit e428c80

Please sign in to comment.