Commit 807945f2 authored by Sergei Petrunia's avatar Sergei Petrunia

MDEV-26402: A SEGV in Item_field::used_tables/update_depend_map_for_order...

When doing condition pushdown from HAVING into WHERE,
Item_equal::create_pushable_equalities() calls
item->set_extraction_flag(IMMUTABLE_FL) for constant items.
Then, Item::cleanup_excluding_immutables_processor() checks for this flag
to see if it should call item->cleanup() or leave the item as-is.

The failure happens when a constant item has a non-constant one inside it,
like:

   (tbl.col=0 AND impossible_cond)

item->walk(cleanup_excluding_immutables_processor) works in a bottom-up
way so it
1. will call Item_func_eq(tbl.col=0)->cleanup()
2. will not call Item_cond_and->cleanup (as the AND is constant)

This creates an item tree where a fixed Item has an un-fixed Item inside
it which eventually causes an assertion failure.

Fixed by introducing this rule: instead of just calling

  item->set_extraction_flag(IMMUTABLE_FL);

we call Item::walk() to set the flag for all sub-items of the item.
parent 32041e70
......@@ -4924,3 +4924,18 @@ SELECT a FROM t1 GROUP BY a HAVING a = ( SELECT MIN(c) FROM t2 );
a
2
DROP TABLE t1,t2;
#
# MDEV-26402: A SEGV in Item_field::used_tables/update_depend_map_for_order or Assertion `fixed == 1'
#
CREATE TABLE t1 (i int NOT NULL);
SELECT * FROM t1 GROUP BY i HAVING i IN ( i IS NULL);
i
SELECT * FROM t1 GROUP BY i HAVING i IN ( i IS NULL AND 'x' = 0);
i
Warnings:
Warning 1292 Truncated incorrect DOUBLE value: 'x'
SELECT * FROM t1 GROUP BY i HAVING i='1' IN ( i IS NULL AND 'x' = 0);
i
Warnings:
Warning 1292 Truncated incorrect DOUBLE value: 'x'
DROP TABLE t1;
......@@ -1440,3 +1440,13 @@ eval EXPLAIN FORMAT=JSON $q;
eval $q;
DROP TABLE t1,t2;
--echo #
--echo # MDEV-26402: A SEGV in Item_field::used_tables/update_depend_map_for_order or Assertion `fixed == 1'
--echo #
CREATE TABLE t1 (i int NOT NULL);
SELECT * FROM t1 GROUP BY i HAVING i IN ( i IS NULL);
SELECT * FROM t1 GROUP BY i HAVING i IN ( i IS NULL AND 'x' = 0);
SELECT * FROM t1 GROUP BY i HAVING i='1' IN ( i IS NULL AND 'x' = 0);
DROP TABLE t1;
......@@ -1938,6 +1938,12 @@ class Item: public Value_source,
return 0;
}
virtual bool set_extraction_flag_processor(void *arg)
{
set_extraction_flag(*(int*)arg);
return 0;
}
/**
Check db/table_name if they defined in item and match arg values
......
......@@ -7533,7 +7533,17 @@ bool Item_equal::create_pushable_equalities(THD *thd,
if (!eq || equalities->push_back(eq, thd->mem_root))
return true;
if (!clone_const)
right_item->set_extraction_flag(IMMUTABLE_FL);
{
/*
Also set IMMUTABLE_FL for any sub-items of the right_item.
This is needed to prevent Item::cleanup_excluding_immutables_processor
from peforming cleanup of the sub-items and so creating an item tree
where a fixed item has non-fixed items inside it.
*/
int new_flag= IMMUTABLE_FL;
right_item->walk(&Item::set_extraction_flag_processor, false,
(void*)&new_flag);
}
}
while ((item=it++))
......
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