Commit c8866892 authored by Sergei Petrunia's avatar Sergei Petrunia

MDEV-32320: Server crashes at TABLE::add_tmp_key

The code inside Item_subselect::fix_fields() could fail to check
that left expression had an Item_row, like this:

  (('x', 1.0) ,1) IN (SELECT 'x', 1.23 FROM ... UNION ...)

In order to hit the failure, the first SELECT of the subquery had
to be a degenerate no-tables select. In this case, execution will
not enter into Item_in_subselect::create_row_in_to_exists_cond()
and will not check if left_expr is composed of scalars.

But the subquery is a UNION so as a whole it is not degenerate.
We try to create an expression cache for the subquery.
We create a temp.table from left_expr columns. No field is created
for the Item_row. Then, we crash when trying to add an index over a
non-existent field.

Fixed by moving the left_expr cardinality check to a point in
check_and_do_in_subquery_rewrites() which gets executed for all
cases.
It's better to make the check early so we don't have to care about
subquery rewrite code hitting Item_row in left_expr.
parent d594f1e5
...@@ -3183,4 +3183,34 @@ id select_type table type possible_keys key key_len ref rows Extra ...@@ -3183,4 +3183,34 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 100 2 MATERIALIZED t2 ALL NULL NULL NULL NULL 100
drop table t0, t1, t2; drop table t0, t1, t2;
#
# MDEV-32320: Server crashes at TABLE::add_tmp_key
#
select
( ( 'x' , 1.000000 ) , 1 )
IN
(SELECT
'x' , 'x'
WHERE ( 'x' )
UNION
SELECT 1 , 'x'
HAVING 1 != 1
) as T;
ERROR 21000: Operand should contain 2 column(s)
SELECT
EXISTS (
WITH x ( x ) AS ( SELECT 1 )
SELECT NULL
WHERE ( 1 , 1 ) =
(SELECT
1 , ( ( x , 1.000000 ) , 1 )
IN
(SELECT 'x' , 'x' WHERE ( ( 'x' ) )
UNION
SELECT 1 , x HAVING 1 != 1
)
FROM x
)
);
ERROR 21000: Operand should contain 2 column(s)
# End of 10.4 tests # End of 10.4 tests
...@@ -2596,4 +2596,38 @@ select * from t1 where t1.a in (select t2.a from t2 order by t2.b); ...@@ -2596,4 +2596,38 @@ select * from t1 where t1.a in (select t2.a from t2 order by t2.b);
drop table t0, t1, t2; drop table t0, t1, t2;
--echo #
--echo # MDEV-32320: Server crashes at TABLE::add_tmp_key
--echo #
--error ER_OPERAND_COLUMNS
select
( ( 'x' , 1.000000 ) , 1 )
IN
(SELECT
'x' , 'x'
WHERE ( 'x' )
UNION
SELECT 1 , 'x'
HAVING 1 != 1
) as T;
--error ER_OPERAND_COLUMNS
SELECT
EXISTS (
WITH x ( x ) AS ( SELECT 1 )
SELECT NULL
WHERE ( 1 , 1 ) =
(SELECT
1 , ( ( x , 1.000000 ) , 1 )
IN
(SELECT 'x' , 'x' WHERE ( ( 'x' ) )
UNION
SELECT 1 , x HAVING 1 != 1
)
FROM x
)
);
--echo # End of 10.4 tests --echo # End of 10.4 tests
...@@ -2492,10 +2492,6 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join, ...@@ -2492,10 +2492,6 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join,
(select_lex->ref_pointer_array[i]->type() == REF_ITEM && (select_lex->ref_pointer_array[i]->type() == REF_ITEM &&
((Item_ref*)(select_lex->ref_pointer_array[i]))->ref_type() == ((Item_ref*)(select_lex->ref_pointer_array[i]))->ref_type() ==
Item_ref::OUTER_REF)); Item_ref::OUTER_REF));
if (select_lex->ref_pointer_array[i]->
check_cols(left_expr->element_index(i)->cols()))
DBUG_RETURN(true);
Item *item_eq= Item *item_eq=
new (thd->mem_root) new (thd->mem_root)
Item_func_eq(thd, new (thd->mem_root) Item_func_eq(thd, new (thd->mem_root)
...@@ -2562,9 +2558,6 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join, ...@@ -2562,9 +2558,6 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join,
(select_lex->ref_pointer_array[i]->type() == REF_ITEM && (select_lex->ref_pointer_array[i]->type() == REF_ITEM &&
((Item_ref*)(select_lex->ref_pointer_array[i]))->ref_type() == ((Item_ref*)(select_lex->ref_pointer_array[i]))->ref_type() ==
Item_ref::OUTER_REF)); Item_ref::OUTER_REF));
if (select_lex->ref_pointer_array[i]->
check_cols(left_expr->element_index(i)->cols()))
DBUG_RETURN(true);
item= new (thd->mem_root) item= new (thd->mem_root)
Item_func_eq(thd, Item_func_eq(thd,
new (thd->mem_root) new (thd->mem_root)
......
...@@ -660,6 +660,14 @@ int check_and_do_in_subquery_rewrites(JOIN *join) ...@@ -660,6 +660,14 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
my_error(ER_OPERAND_COLUMNS, MYF(0), in_subs->left_expr->cols()); my_error(ER_OPERAND_COLUMNS, MYF(0), in_subs->left_expr->cols());
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
uint cols_num= in_subs->left_expr->cols();
for (uint i= 0; i < cols_num; i++)
{
if (select_lex->ref_pointer_array[i]->
check_cols(in_subs->left_expr->element_index(i)->cols()))
DBUG_RETURN(-1);
}
} }
DBUG_PRINT("info", ("Checking if subq can be converted to semi-join")); DBUG_PRINT("info", ("Checking if subq can be converted to semi-join"));
......
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