Skip to content

Commit 807945f

Browse files
committed
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.
1 parent 32041e7 commit 807945f

File tree

4 files changed

+42
-1
lines changed

4 files changed

+42
-1
lines changed

mysql-test/main/having_cond_pushdown.result

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4924,3 +4924,18 @@ SELECT a FROM t1 GROUP BY a HAVING a = ( SELECT MIN(c) FROM t2 );
49244924
a
49254925
2
49264926
DROP TABLE t1,t2;
4927+
#
4928+
# MDEV-26402: A SEGV in Item_field::used_tables/update_depend_map_for_order or Assertion `fixed == 1'
4929+
#
4930+
CREATE TABLE t1 (i int NOT NULL);
4931+
SELECT * FROM t1 GROUP BY i HAVING i IN ( i IS NULL);
4932+
i
4933+
SELECT * FROM t1 GROUP BY i HAVING i IN ( i IS NULL AND 'x' = 0);
4934+
i
4935+
Warnings:
4936+
Warning 1292 Truncated incorrect DOUBLE value: 'x'
4937+
SELECT * FROM t1 GROUP BY i HAVING i='1' IN ( i IS NULL AND 'x' = 0);
4938+
i
4939+
Warnings:
4940+
Warning 1292 Truncated incorrect DOUBLE value: 'x'
4941+
DROP TABLE t1;

mysql-test/main/having_cond_pushdown.test

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1440,3 +1440,13 @@ eval EXPLAIN FORMAT=JSON $q;
14401440
eval $q;
14411441

14421442
DROP TABLE t1,t2;
1443+
1444+
--echo #
1445+
--echo # MDEV-26402: A SEGV in Item_field::used_tables/update_depend_map_for_order or Assertion `fixed == 1'
1446+
--echo #
1447+
1448+
CREATE TABLE t1 (i int NOT NULL);
1449+
SELECT * FROM t1 GROUP BY i HAVING i IN ( i IS NULL);
1450+
SELECT * FROM t1 GROUP BY i HAVING i IN ( i IS NULL AND 'x' = 0);
1451+
SELECT * FROM t1 GROUP BY i HAVING i='1' IN ( i IS NULL AND 'x' = 0);
1452+
DROP TABLE t1;

sql/item.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1938,6 +1938,12 @@ class Item: public Value_source,
19381938
return 0;
19391939
}
19401940

1941+
virtual bool set_extraction_flag_processor(void *arg)
1942+
{
1943+
set_extraction_flag(*(int*)arg);
1944+
return 0;
1945+
}
1946+
19411947
/**
19421948
Check db/table_name if they defined in item and match arg values
19431949

sql/item_cmpfunc.cc

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7533,7 +7533,17 @@ bool Item_equal::create_pushable_equalities(THD *thd,
75337533
if (!eq || equalities->push_back(eq, thd->mem_root))
75347534
return true;
75357535
if (!clone_const)
7536-
right_item->set_extraction_flag(IMMUTABLE_FL);
7536+
{
7537+
/*
7538+
Also set IMMUTABLE_FL for any sub-items of the right_item.
7539+
This is needed to prevent Item::cleanup_excluding_immutables_processor
7540+
from peforming cleanup of the sub-items and so creating an item tree
7541+
where a fixed item has non-fixed items inside it.
7542+
*/
7543+
int new_flag= IMMUTABLE_FL;
7544+
right_item->walk(&Item::set_extraction_flag_processor, false,
7545+
(void*)&new_flag);
7546+
}
75377547
}
75387548

75397549
while ((item=it++))

0 commit comments

Comments
 (0)