Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions mysql-test/main/derived_cond_pushdown.result
Original file line number Diff line number Diff line change
Expand Up @@ -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
13 changes: 13 additions & 0 deletions mysql-test/main/derived_cond_pushdown.test
Original file line number Diff line number Diff line change
Expand Up @@ -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
9 changes: 9 additions & 0 deletions sql/item_cmpfunc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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<Item> li(item->equal_items);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should be able to use List_iterator_fast here instead because you're walking the list and updating elements in the list but not mutating the list itself. List_iterator_fast avoids some extra bookkeeping on the presumption that you're not altering the list itself.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice catch, thanks.

Item *eq_item;
while ((eq_item= li++))
eq_item->set_item_equal(this);
if (c)
{
/*
Expand Down
10 changes: 9 additions & 1 deletion sql/item_cmpfunc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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());

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original implementation implied that equal_items.head() could return NULL. Is it safe to assume, in the assertion, that equal_items.head() is always non-NULL when with_const is true? I suppose that if the equal_items.head() returns NULL, then we will have an assertion-like behavior in that the null pointer dereference will crash, but that's probably not intended.

Should the assertion instead be something like:

DBUG_ASSERT(!with_const || (equal_items.head() && equal_items.head()->const_item()));

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we could ever get an empty equal_items List in our Item_equal object. Even one one item doesn't make any sense.

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); }
Expand Down Expand Up @@ -3614,6 +3618,7 @@ template <template<class> class LI, typename T> class Item_equal_iterator
{
LI<T> *list_it= this;
curr_item= (*list_it)++;
DBUG_ASSERT(curr_item && curr_item->const_item());
}
}
Item* operator++(int)
Expand All @@ -3627,7 +3632,10 @@ template <template<class> class LI, typename T> class Item_equal_iterator
LI<T> *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()
{
Expand Down