diff --git a/mysql-test/main/derived_cond_pushdown.result b/mysql-test/main/derived_cond_pushdown.result index 2824e3061d304..05ba3050fcb39 100644 --- a/mysql-test/main/derived_cond_pushdown.result +++ b/mysql-test/main/derived_cond_pushdown.result @@ -21784,4 +21784,25 @@ select * from v2 where greatest(a, default(a)); a count(*) drop view v2, v1; drop table t1; +# +# MDEV-29360 Crash when pushing condition with always false IS NULL +# into derived contains constant TRUE/FALSE as subformula +# +create table t1 (id int not null); +insert into t1 values (0),(1),(3); +create table t2 select * from t1; +create table t3 select * from t1; +set optimizer_trace='enabled=on'; +select * from (select id from t1 group by id) dt1, (select id from t2) dt2, t3 +where dt2.id = t3.id and dt1.id between 0 and (dt2.id is null); +id id id +0 0 0 +0 1 1 +0 3 3 +select json_extract((select trace from information_schema.optimizer_trace), +'$**.grouping_field_transformer_for_where') as trace; +trace +[{"before": "t2.`id`", "after": "1"}] +set optimizer_trace='enabled=off'; +drop table t1,t2,t3; # End of 10.11 tests diff --git a/mysql-test/main/derived_cond_pushdown.test b/mysql-test/main/derived_cond_pushdown.test index f00cdde5df2c1..79a20675d0afa 100644 --- a/mysql-test/main/derived_cond_pushdown.test +++ b/mysql-test/main/derived_cond_pushdown.test @@ -4351,4 +4351,26 @@ select * from v2 where greatest(a, default(a)); drop view v2, v1; drop table t1; +--echo # +--echo # MDEV-29360 Crash when pushing condition with always false IS NULL +--echo # into derived contains constant TRUE/FALSE as subformula +--echo # + +create table t1 (id int not null); +insert into t1 values (0),(1),(3); +create table t2 select * from t1; +create table t3 select * from t1; + +set optimizer_trace='enabled=on'; + +select * from (select id from t1 group by id) dt1, (select id from t2) dt2, t3 + where dt2.id = t3.id and dt1.id between 0 and (dt2.id is null); + +select json_extract((select trace from information_schema.optimizer_trace), + '$**.grouping_field_transformer_for_where') as trace; + +set optimizer_trace='enabled=off'; + +drop table t1,t2,t3; + --echo # End of 10.11 tests diff --git a/sql/item.cc b/sql/item.cc index a3ec31ceea8b0..507fe21e22963 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -8171,7 +8171,10 @@ Item_direct_view_ref::grouping_field_transformer_for_where(THD *thd, st_select_lex *sel= (st_select_lex *)arg; Field_pair *gr_field= find_matching_field_pair(this, sel->grouping_tmp_fields); - return gr_field->corresponding_item->deep_copy_with_checks(thd); + if (gr_field) + return gr_field->corresponding_item->deep_copy_with_checks(thd); + else + return this; } void Item_field::print(String *str, enum_query_type query_type) diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 5f2c471de7fba..7ae5dc25ebd76 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -7975,3 +7975,22 @@ Item *Item_equal::multiple_equality_transformer(THD *thd, uchar *arg) break; } } + + +Item *Item_func_isnull::grouping_field_transformer_for_where(THD *thd, + uchar *arg) + { + if (const_item_cache) + { + Json_writer_object trace_wrapper(thd); + Json_writer_object trace_xform(thd, "grouping_field_transformer_for_where"); + trace_xform.add("before", args[0]); + + if (Item *item= new (thd->mem_root) Item_int(thd, 1)) + args[0]= item; + else + return 0; + trace_xform.add("after", args[0]); + } + return this; + } diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 753d939f6560d..12af8ba014ce3 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -2859,6 +2859,7 @@ class Item_func_isnull :public Item_func_null_predicate const_item_cache= args[0]->const_item(); } } + Item *grouping_field_transformer_for_where(THD *thd, uchar *arg) override; COND *remove_eq_conds(THD *thd, Item::cond_result *cond_value, bool top_level) override; table_map not_null_tables() const override { return 0; }