mirror of
https://github.com/MariaDB/server.git
synced 2025-03-30 11:55:31 +02:00
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.
This commit is contained in:
parent
d594f1e531
commit
c886689261
4 changed files with 72 additions and 7 deletions
|
@ -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
|
||||
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 100
|
||||
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
|
||||
|
|
|
@ -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;
|
||||
|
||||
--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
|
||||
|
|
|
@ -2492,10 +2492,6 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join,
|
|||
(select_lex->ref_pointer_array[i]->type() == REF_ITEM &&
|
||||
((Item_ref*)(select_lex->ref_pointer_array[i]))->ref_type() ==
|
||||
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=
|
||||
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,
|
|||
(select_lex->ref_pointer_array[i]->type() == REF_ITEM &&
|
||||
((Item_ref*)(select_lex->ref_pointer_array[i]))->ref_type() ==
|
||||
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_func_eq(thd,
|
||||
new (thd->mem_root)
|
||||
|
|
|
@ -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());
|
||||
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"));
|
||||
|
|
Loading…
Add table
Reference in a new issue