mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01:00
MDEV-24840 Crash caused by query with IN subquery containing union
of two table value costructors This bug affected queries with a [NOT] IN/ANY/ALL subquery whose top level unit contained several table value constructors. The problem appeared because the code of the function Item_subselect::fix_fields() that was responsible for wrapping table value constructors encountered at the top level unit of a [NOT] IN/ANY/ALL subquery did not take into account that the chain of the select objects comprising the unit were not immutable. Approved by Oleksandr Byelkin <sanja@mariadb.com>
This commit is contained in:
parent
59eda73eff
commit
da88e1ec12
5 changed files with 113 additions and 7 deletions
|
@ -2674,4 +2674,72 @@ values (1,2);
|
|||
values ((select min(a), max(b) from t1));
|
||||
ERROR 21000: Operand should contain 1 column(s)
|
||||
drop table t1;
|
||||
#
|
||||
# MDEV-24840: union of TVCs in IN subquery
|
||||
#
|
||||
create table t1 (a int) engine=myisam;
|
||||
insert into t1 values (3), (7), (1);
|
||||
select a from t1 where a in (values (7) union values (8));
|
||||
a
|
||||
7
|
||||
explain extended select a from t1 where a in (values (7) union values (8));
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
4 DEPENDENT SUBQUERY <derived2> ref key0 key0 4 func 2 100.00
|
||||
2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||
5 DEPENDENT UNION <derived3> ref key0 key0 4 func 2 100.00
|
||||
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||
NULL UNION RESULT <union4,5> ALL NULL NULL NULL NULL NULL NULL
|
||||
Warnings:
|
||||
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where <expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,<exists>(/* select#4 */ select `tvc_0`.`7` from (values (7)) `tvc_0` where <cache>(`test`.`t1`.`a`) = `tvc_0`.`7` union /* select#5 */ select `tvc_0`.`8` from (values (8)) `tvc_0` where <cache>(`test`.`t1`.`a`) = `tvc_0`.`8`)))
|
||||
prepare stmt from "select a from t1 where a in (values (7) union values (8))";
|
||||
execute stmt;
|
||||
a
|
||||
7
|
||||
execute stmt;
|
||||
a
|
||||
7
|
||||
deallocate prepare stmt;
|
||||
select a from t1 where a not in (values (7) union values (8));
|
||||
a
|
||||
3
|
||||
1
|
||||
explain extended select a from t1 where a not in (values (7) union values (8));
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
4 DEPENDENT SUBQUERY <derived2> ALL NULL NULL NULL NULL 2 100.00 Using where
|
||||
2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||
5 DEPENDENT UNION <derived3> ALL NULL NULL NULL NULL 2 100.00 Using where
|
||||
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||
NULL UNION RESULT <union4,5> ALL NULL NULL NULL NULL NULL NULL
|
||||
Warnings:
|
||||
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where !<expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,<exists>(/* select#4 */ select `tvc_0`.`7` from (values (7)) `tvc_0` where trigcond(<cache>(`test`.`t1`.`a`) = `tvc_0`.`7`) union /* select#5 */ select `tvc_0`.`8` from (values (8)) `tvc_0` where trigcond(<cache>(`test`.`t1`.`a`) = `tvc_0`.`8`))))
|
||||
select a from t1 where a < all(values (7) union values (8));
|
||||
a
|
||||
3
|
||||
1
|
||||
explain extended select a from t1 where a < all(values (7) union values (8));
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
4 SUBQUERY <derived2> ALL NULL NULL NULL NULL 2 100.00
|
||||
2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||
5 UNION <derived3> ALL NULL NULL NULL NULL 2 100.00
|
||||
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||
NULL UNION RESULT <union4,5> ALL NULL NULL NULL NULL NULL NULL
|
||||
Warnings:
|
||||
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where <not>(<in_optimizer>(`test`.`t1`.`a`,<min>(/* select#4 */ select `tvc_0`.`7` from (values (7)) `tvc_0` union /* select#5 */ select `tvc_0`.`8` from (values (8)) `tvc_0`) <= <cache>(`test`.`t1`.`a`)))
|
||||
select a from t1 where a >= any(values (7) union values (8));
|
||||
a
|
||||
7
|
||||
explain extended select a from t1 where a >= any(values (7) union values (8));
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
4 SUBQUERY <derived2> ALL NULL NULL NULL NULL 2 100.00
|
||||
2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||
5 UNION <derived3> ALL NULL NULL NULL NULL 2 100.00
|
||||
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||
NULL UNION RESULT <union4,5> ALL NULL NULL NULL NULL NULL NULL
|
||||
Warnings:
|
||||
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where <nop>(<in_optimizer>(`test`.`t1`.`a`,<min>(/* select#4 */ select `tvc_0`.`7` from (values (7)) `tvc_0` union /* select#5 */ select `tvc_0`.`8` from (values (8)) `tvc_0`) <= <cache>(`test`.`t1`.`a`)))
|
||||
drop table t1;
|
||||
End of 10.3 tests
|
||||
|
|
|
@ -1401,4 +1401,37 @@ values ((select min(a), max(b) from t1));
|
|||
|
||||
drop table t1;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-24840: union of TVCs in IN subquery
|
||||
--echo #
|
||||
|
||||
create table t1 (a int) engine=myisam;
|
||||
insert into t1 values (3), (7), (1);
|
||||
|
||||
let $q=
|
||||
select a from t1 where a in (values (7) union values (8));
|
||||
eval $q;
|
||||
eval explain extended $q;
|
||||
eval prepare stmt from "$q";
|
||||
execute stmt;
|
||||
execute stmt;
|
||||
deallocate prepare stmt;
|
||||
|
||||
let $q=
|
||||
select a from t1 where a not in (values (7) union values (8));
|
||||
eval $q;
|
||||
eval explain extended $q;
|
||||
|
||||
let $q=
|
||||
select a from t1 where a < all(values (7) union values (8));
|
||||
eval $q;
|
||||
eval explain extended $q;
|
||||
|
||||
let $q=
|
||||
select a from t1 where a >= any(values (7) union values (8));
|
||||
eval $q;
|
||||
eval explain extended $q;
|
||||
|
||||
drop table t1;
|
||||
|
||||
--echo End of 10.3 tests
|
||||
|
|
|
@ -269,7 +269,11 @@ bool Item_subselect::fix_fields(THD *thd_param, Item **ref)
|
|||
{
|
||||
if (sl->tvc)
|
||||
{
|
||||
wrap_tvc_into_select(thd, sl);
|
||||
if (!(sl= wrap_tvc_into_select(thd, sl)))
|
||||
{
|
||||
res= TRUE;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -271,7 +271,7 @@ public:
|
|||
Item* build_clone(THD *thd) { return 0; }
|
||||
Item* get_copy(THD *thd) { return 0; }
|
||||
|
||||
bool wrap_tvc_into_select(THD *thd, st_select_lex *tvc_sl);
|
||||
st_select_lex *wrap_tvc_into_select(THD *thd, st_select_lex *tvc_sl);
|
||||
|
||||
friend class select_result_interceptor;
|
||||
friend class Item_in_optimizer;
|
||||
|
|
|
@ -779,11 +779,12 @@ st_select_lex *wrap_tvc_with_tail(THD *thd, st_select_lex *tvc_sl)
|
|||
SELECT * FROM (VALUES (v1), ... (vn)) tvc_x
|
||||
and replaces the subselect with the result of the transformation.
|
||||
|
||||
@retval false if successfull
|
||||
true otherwise
|
||||
@retval wrapping select if successful
|
||||
0 otherwise
|
||||
*/
|
||||
|
||||
bool Item_subselect::wrap_tvc_into_select(THD *thd, st_select_lex *tvc_sl)
|
||||
st_select_lex *
|
||||
Item_subselect::wrap_tvc_into_select(THD *thd, st_select_lex *tvc_sl)
|
||||
{
|
||||
LEX *lex= thd->lex;
|
||||
/* SELECT_LEX object where the transformation is performed */
|
||||
|
@ -794,12 +795,12 @@ bool Item_subselect::wrap_tvc_into_select(THD *thd, st_select_lex *tvc_sl)
|
|||
if (engine->engine_type() == subselect_engine::SINGLE_SELECT_ENGINE)
|
||||
((subselect_single_select_engine *) engine)->change_select(wrapper_sl);
|
||||
lex->current_select= wrapper_sl;
|
||||
return false;
|
||||
return wrapper_sl;
|
||||
}
|
||||
else
|
||||
{
|
||||
lex->current_select= parent_select;
|
||||
return true;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue