Commit 5dc9a6b4 authored by Igor Babaev's avatar Igor Babaev

MDEV-31102 Crash when pushing condition into view defined as union

This bug could manifest itself at the first execution of prepared statement
created for queries using a materialized view defined as union. A crash
could happen for sure if the query contained a condition pushable into
the view and this condition was over the column defined via a complex string
expression requiring implicit conversion from one charset to another for
some of its sub-expressions. The bug could cause crashes when executing
PS for some other queries whose optimization needed building clones for
such expressions.

This bug was introduced in the patch for MDEV-29988 where the class
Item_direct_ref_to_item was added. The implementations of the virtual
methods get_copy() and build_clone() were invalid for the class and this
could cause crashes after the method build_clone() was called for
expressions containing objects of the Item_direct_ref_to_item type.

Approved by Sergei Golubchik <serg@mariadb.com>
parent d3e394b3
......@@ -18275,4 +18275,87 @@ id select_type table type possible_keys key key_len ref rows Extra
3 DERIVED t1 ALL NULL NULL NULL NULL 3 Using temporary
drop view v1;
drop table t1;
#
# MDEV-31102: execution of PS for query where pushdown of condition
# into view defined as union is applied
#
create table t1 (
n int,
lv varchar(31) charset latin1,
mv varchar(31) charset utf8mb3
) engine=myisam;
insert into t1 values (1,'aa','xxx'), ('2','bb','yyy'), (3,'cc','zzz');
create view v1 as
select case when n=1 then lv when n=2 then mv else NULL end as r from t1
union
select 'a';
select * from v1 where r < 'x';
r
aa
a
explain extended select * from v1 where r < 'x';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 3 100.00 Using where
2 DERIVED t1 ALL NULL NULL NULL NULL 3 100.00 Using where
3 UNION NULL NULL NULL NULL NULL NULL NULL NULL No tables used
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
Note 1003 /* select#1 */ select `v1`.`r` AS `r` from `test`.`v1` where `v1`.`r` < 'x'
explain format=json select * from v1 where r < 'x';
EXPLAIN
{
"query_block": {
"select_id": 1,
"table": {
"table_name": "<derived2>",
"access_type": "ALL",
"rows": 3,
"filtered": 100,
"attached_condition": "v1.r < 'x'",
"materialized": {
"query_block": {
"union_result": {
"table_name": "<union2,3>",
"access_type": "ALL",
"query_specifications": [
{
"query_block": {
"select_id": 2,
"table": {
"table_name": "t1",
"access_type": "ALL",
"rows": 3,
"filtered": 100,
"attached_condition": "case when t1.n = 1 then convert(t1.lv using utf8) when t1.n = 2 then t1.mv else NULL end < 'x'"
}
}
},
{
"query_block": {
"select_id": 3,
"operation": "UNION",
"table": {
"message": "No tables used"
}
}
}
]
}
}
}
}
}
}
prepare stmt from "select * from v1 where r < 'x'";
execute stmt;
r
aa
a
execute stmt;
r
aa
a
deallocate prepare stmt;
drop view v1;
drop table t1;
# End of 10.4 tests
......@@ -3942,4 +3942,34 @@ explain select * from v1;
drop view v1;
drop table t1;
--echo #
--echo # MDEV-31102: execution of PS for query where pushdown of condition
--echo # into view defined as union is applied
--echo #
create table t1 (
n int,
lv varchar(31) charset latin1,
mv varchar(31) charset utf8mb3
) engine=myisam;
insert into t1 values (1,'aa','xxx'), ('2','bb','yyy'), (3,'cc','zzz');
create view v1 as
select case when n=1 then lv when n=2 then mv else NULL end as r from t1
union
select 'a';
let $q=
select * from v1 where r < 'x';
eval $q;
eval explain extended $q;
eval explain format=json $q;
eval prepare stmt from "$q";
execute stmt;
execute stmt;
deallocate prepare stmt;
drop view v1;
drop table t1;
--echo # End of 10.4 tests
......@@ -7647,7 +7647,7 @@ class Item_direct_ref_to_item : public Item_direct_ref
Item *get_tmp_table_item(THD *thd)
{ return m_item->get_tmp_table_item(thd); }
Item *get_copy(THD *thd)
{ return m_item->get_copy(thd); }
{ return get_item_copy<Item_direct_ref_to_item>(thd, this); }
COND *build_equal_items(THD *thd, COND_EQUAL *inherited,
bool link_item_fields,
COND_EQUAL **cond_equal_ref)
......@@ -7715,7 +7715,20 @@ class Item_direct_ref_to_item : public Item_direct_ref
bool excl_dep_on_grouping_fields(st_select_lex *sel)
{ return m_item->excl_dep_on_grouping_fields(sel); }
bool is_expensive() { return m_item->is_expensive(); }
Item* build_clone(THD *thd) { return get_copy(thd); }
void set_item(Item *item) { m_item= item; }
Item *build_clone(THD *thd)
{
Item *clone_item= m_item->build_clone(thd);
if (clone_item)
{
Item_direct_ref_to_item *copy= (Item_direct_ref_to_item *) get_copy(thd);
if (!copy)
return 0;
copy->set_item(clone_item);
return copy;
}
return 0;
}
void split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array,
List<Item> &fields, uint flags)
......
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