summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Babaev <igor@askmonty.org>2023-04-21 13:46:14 -0700
committerIgor Babaev <igor@askmonty.org>2023-04-24 07:39:19 -0700
commit5dc9a6b4558d50298882b3d76b3249e9419e3682 (patch)
treee02e86325713b391b7a769675785e112a8a0720a
parentd3e394b3b1ff1e2c4e160972aad1f78a13fbb62e (diff)
downloadmariadb-git-5dc9a6b4558d50298882b3d76b3249e9419e3682.tar.gz
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>
-rw-r--r--mysql-test/main/derived_cond_pushdown.result83
-rw-r--r--mysql-test/main/derived_cond_pushdown.test30
-rw-r--r--sql/item.h17
3 files changed, 128 insertions, 2 deletions
diff --git a/mysql-test/main/derived_cond_pushdown.result b/mysql-test/main/derived_cond_pushdown.result
index 41f9ac6fca1..4b202ea7a12 100644
--- a/mysql-test/main/derived_cond_pushdown.result
+++ b/mysql-test/main/derived_cond_pushdown.result
@@ -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
diff --git a/mysql-test/main/derived_cond_pushdown.test b/mysql-test/main/derived_cond_pushdown.test
index 6cfe23b7866..b4e131dbe79 100644
--- a/mysql-test/main/derived_cond_pushdown.test
+++ b/mysql-test/main/derived_cond_pushdown.test
@@ -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
diff --git a/sql/item.h b/sql/item.h
index 31568aafc8c..1e0caaa7c83 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -7647,7 +7647,7 @@ public:
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 @@ public:
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)