Skip to content

Commit 151631b

Browse files
GoldenEmperor1177KhaledR57
authored andcommitted
MDEV-31225 Crash converting IN with a nested ROW into IN subquery
What was wrong: With in_predicate_conversion_threshold set low enough, an IN predicate with a nested ROW, e.g. ROW(a,(a,a)) IN ((1,(1,1)),(2,(2,NULL))) crashed the server. Before an IN list is converted into an IN subquery over a table value constructor, cmp_row_types() checks every column with subquery_type_allows_materialization(). With a nested ROW the column is a ROW itself, and for a ROW that function must not be called. How it is fixed: A table value constructor cannot have a ROW as a column, so such a predicate cannot be converted anyway. cmp_row_types() now reports the columns as not comparable when either of them is a ROW, and the IN predicate is evaluated without the conversion. How it is tested: Added a test to main.opt_tvc with IN and NOT IN over nested ROWs. It crashes the server without the fix.
1 parent b078861 commit 151631b

3 files changed

Lines changed: 47 additions & 0 deletions

File tree

‎mysql-test/main/opt_tvc.result‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -791,4 +791,24 @@ select * from t1 where a in (1, 2) and b = 2 order by a, b;
791791
a b c
792792
1 2 NULL
793793
drop table t1;
794+
#
795+
# MDEV-31225: Signal 11 after select ..WHERE ROW(a,(a,a)) IN
796+
# ((1,(1,1)),(2,(2,null))) with in_predicate_conversion_threshold=1
797+
#
798+
create table t1 (a int);
799+
insert into t1 values (1), (2), (3);
800+
set in_predicate_conversion_threshold=1;
801+
explain extended select a from t1 where row(a,(a,a)) in ((1,(1,1)),(2,(2,null)));
802+
id select_type table type possible_keys key key_len ref rows filtered Extra
803+
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
804+
Warnings:
805+
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a`,(`test`.`t1`.`a`,`test`.`t1`.`a`)) in (<cache>((1,(1,1))),<cache>((2,(2,NULL))))
806+
select a from t1 where row(a,(a,a)) in ((1,(1,1)),(2,(2,null)));
807+
a
808+
1
809+
select a from t1 where row(a,(a,a)) not in ((1,(1,1)),(2,(2,2)));
810+
a
811+
3
812+
drop table t1;
813+
set in_predicate_conversion_threshold=default;
794814
# End of 11.4 tests

‎mysql-test/main/opt_tvc.test‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,4 +488,25 @@ select * from t1 where a in (1, 2) and b = 2 order by a, b;
488488

489489
drop table t1;
490490

491+
--echo #
492+
--echo # MDEV-31225: Signal 11 after select ..WHERE ROW(a,(a,a)) IN
493+
--echo # ((1,(1,1)),(2,(2,null))) with in_predicate_conversion_threshold=1
494+
--echo #
495+
496+
create table t1 (a int);
497+
insert into t1 values (1), (2), (3);
498+
499+
set in_predicate_conversion_threshold=1;
500+
501+
let $query=
502+
select a from t1 where row(a,(a,a)) in ((1,(1,1)),(2,(2,null)));
503+
eval explain extended $query;
504+
eval $query;
505+
506+
select a from t1 where row(a,(a,a)) not in ((1,(1,1)),(2,(2,2)));
507+
508+
drop table t1;
509+
510+
set in_predicate_conversion_threshold=default;
511+
491512
--echo # End of 11.4 tests

‎sql/sql_tvc.cc‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -894,6 +894,12 @@ static bool cmp_row_types(Item* item1, Item* item2)
894894
{
895895
Item *inner= item1->element_index(i);
896896
Item *outer= item2->element_index(i);
897+
/*
898+
A table value constructor cannot have a ROW as a column, so an IN
899+
predicate with a nested ROW cannot be converted.
900+
*/
901+
if (inner->cols() != 1 || outer->cols() != 1)
902+
return true;
897903
if (!inner->type_handler()->subquery_type_allows_materialization(inner,
898904
outer,
899905
true))

0 commit comments

Comments
 (0)