diff --git a/mysql-test/main/derived_cond_pushdown.result b/mysql-test/main/derived_cond_pushdown.result index ff72ea59b8ea0..7489e3ef2fa34 100644 --- a/mysql-test/main/derived_cond_pushdown.result +++ b/mysql-test/main/derived_cond_pushdown.result @@ -21807,4 +21807,15 @@ id id id 0 1 1 0 3 3 drop table t1,t2,t3; +# +# MDEV-26940 Item_cond::remove_eq_conds leaves corrupt Item_equal +# +CREATE TABLE t (f INT); +CREATE VIEW v1 AS SELECT COUNT(*) as c FROM t; +CREATE VIEW v2 AS SELECT a2.c FROM v1 AS a1, v1 AS a2 +WHERE a1.c = a2.c OR a2.c <= 10; +SELECT c FROM v2 WHERE c = 83; +c +DROP VIEW v1, v2; +DROP TABLE t; # End of 10.11 tests diff --git a/mysql-test/main/derived_cond_pushdown.test b/mysql-test/main/derived_cond_pushdown.test index 8a5a7266e0733..b0b3990ac5323 100644 --- a/mysql-test/main/derived_cond_pushdown.test +++ b/mysql-test/main/derived_cond_pushdown.test @@ -4371,4 +4371,17 @@ select * from (select id from t1 union select id from t2) dt1, drop table t1,t2,t3; +--echo # +--echo # MDEV-26940 Item_cond::remove_eq_conds leaves corrupt Item_equal +--echo # + +CREATE TABLE t (f INT); +CREATE VIEW v1 AS SELECT COUNT(*) as c FROM t; +CREATE VIEW v2 AS SELECT a2.c FROM v1 AS a1, v1 AS a2 + WHERE a1.c = a2.c OR a2.c <= 10; +SELECT c FROM v2 WHERE c = 83; + +DROP VIEW v1, v2; +DROP TABLE t; + --echo # End of 10.11 tests diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 5f2c471de7fba..fb6c69923b9fa 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -7045,6 +7045,15 @@ void Item_equal::merge(THD *thd, Item_equal *item) if (c) item->equal_items.pop(); equal_items.append(&item->equal_items); + /* + The members just merged in still point back at 'item', which is now + abandoned and left in an invalid state. Repoint their item_equal + back-pointers at 'this' so nothing follows them to the orphan. + */ + List_iterator li(item->equal_items); + Item *eq_item; + while ((eq_item= li++)) + eq_item->set_item_equal(this); if (c) { /* diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 66db4361d7253..0d6d487fe2080 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -3481,7 +3481,11 @@ class Item_equal: public Item_bool_func Item *f1, Item *f2, bool with_const_item); Item_equal(THD *thd, Item_equal *item_equal); /* Currently the const item is always the first in the list of equal items */ - inline Item* get_const() { return with_const ? equal_items.head() : NULL; } + inline Item* get_const() + { + DBUG_ASSERT(!with_const || equal_items.head()->const_item()); + return with_const ? equal_items.head() : NULL; + } void add_const(THD *thd, Item *c); /** Add a non-constant item to the multiple equality */ void add(Item *f, MEM_ROOT *root) { equal_items.push_back(f, root); } @@ -3614,6 +3618,7 @@ template class LI, typename T> class Item_equal_iterator { LI *list_it= this; curr_item= (*list_it)++; + DBUG_ASSERT(curr_item && curr_item->const_item()); } } Item* operator++(int) @@ -3627,7 +3632,10 @@ template class LI, typename T> class Item_equal_iterator LI *list_it= this; list_it->rewind(); if (item_equal->with_const) + { curr_item= (*list_it)++; + DBUG_ASSERT(curr_item && curr_item->const_item()); + } } Field *get_curr_field() {