mirror of
https://github.com/MariaDB/server.git
synced 2025-01-15 19:42:28 +01:00
MDEV-29363: Constant subquery causing a crash in pushdown optimization
The crash is caused by the attempt to refix the constant subquery during pushdown from HAVING into WHERE optimization. Every condition that is going to be pushed into WHERE clause is first cleaned up, then refixed. Constant subqueries are not cleaned or refixed because they will remain the same after refixing, so this complicated procedure can be omitted for them (introduced in MDEV-21184). Constant subqueries are marked with flag IMMUTABLE_FL, that helps to miss the cleanup stage for them. Also they are marked as fixed, so refixing is also not done for them. Because of the multiple equality propagation several references to the same constant subquery can exist in the condition that is going to be pushed into WHERE. Before this patch, the problem appeared in the following way. After the first reference to the constant subquery is processed, the flag IMMUTABLE_FL for the constant subquery is disabled. So, when the second reference to this constant subquery is processed, the flag is already disabled and the subquery goes through the procedure of cleaning and refixing. That causes a crash. To solve this problem, IMMUTABLE_FL should be disabled only after all references to the constant subquery are processed, so after the whole condition that is going to be pushed is cleaned up and refixed. Approved by Igor Babaev <igor@maridb.com>
This commit is contained in:
parent
a4ef05d0d5
commit
6cb896a639
5 changed files with 194 additions and 3 deletions
|
@ -4982,3 +4982,114 @@ a
|
|||
0
|
||||
DROP TABLE t1;
|
||||
End of 10.4 tests
|
||||
#
|
||||
# MDEV-29363: Constant subquery causing a crash in pushdown optimization
|
||||
#
|
||||
CREATE TABLE t1 (a INT, b INT, c INT);
|
||||
INSERT INTO t1 VALUES (3, 3, 4), (NULL, NULL, 2);
|
||||
EXPLAIN FORMAT=JSON SELECT a,b,c FROM t1 GROUP BY a,b,c
|
||||
HAVING a = (SELECT MIN(b) AS min_b FROM t1) and (a = b or a = c);
|
||||
EXPLAIN
|
||||
{
|
||||
"query_block": {
|
||||
"select_id": 1,
|
||||
"filesort": {
|
||||
"sort_key": "t1.b, t1.c",
|
||||
"temporary_table": {
|
||||
"table": {
|
||||
"table_name": "t1",
|
||||
"access_type": "ALL",
|
||||
"rows": 2,
|
||||
"filtered": 100,
|
||||
"attached_condition": "t1.a = (subquery#2) and (t1.b = (subquery#2) or t1.c = (subquery#2))"
|
||||
},
|
||||
"subqueries": [
|
||||
{
|
||||
"query_block": {
|
||||
"select_id": 2,
|
||||
"table": {
|
||||
"table_name": "t1",
|
||||
"access_type": "ALL",
|
||||
"rows": 2,
|
||||
"filtered": 100
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
SELECT a,b,c FROM t1 GROUP BY a,b,c
|
||||
HAVING a = (SELECT MIN(b) AS min_b FROM t1) and (a = b or a = c);
|
||||
a b c
|
||||
3 3 4
|
||||
EXPLAIN FORMAT=JSON SELECT a FROM t1 GROUP BY a,b
|
||||
HAVING a = (SELECT MIN(a) AS min_a FROM t1) AND (a = 3 or a > b);
|
||||
EXPLAIN
|
||||
{
|
||||
"query_block": {
|
||||
"select_id": 1,
|
||||
"filesort": {
|
||||
"sort_key": "t1.b",
|
||||
"temporary_table": {
|
||||
"table": {
|
||||
"table_name": "t1",
|
||||
"access_type": "ALL",
|
||||
"rows": 2,
|
||||
"filtered": 100,
|
||||
"attached_condition": "t1.a = (subquery#2) and (1 or (subquery#2) > t1.b)"
|
||||
},
|
||||
"subqueries": [
|
||||
{
|
||||
"query_block": {
|
||||
"select_id": 2,
|
||||
"table": {
|
||||
"table_name": "t1",
|
||||
"access_type": "ALL",
|
||||
"rows": 2,
|
||||
"filtered": 100
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
SELECT a FROM t1 GROUP BY a,b
|
||||
HAVING a = (SELECT MIN(a) AS min_a FROM t1) AND (a = 3 or a > b);
|
||||
a
|
||||
3
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# MDEV-32424: Pushdown: server crashes at JOIN::save_explain_data()
|
||||
# (fixed by the patch for MDEV-29363)
|
||||
#
|
||||
CREATE TABLE t1 (a INT, b INT, c INT);
|
||||
INSERT INTO t1 VALUES (1, 1, 3), (3, 2, 3);
|
||||
SELECT a,b,c FROM t1 GROUP BY a,b,c
|
||||
HAVING a = (SELECT MIN(b) AS min_b FROM t1) and a IN (b, c);
|
||||
a b c
|
||||
1 1 3
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# MDEV-32293: Pushdown: server crashes at check_simple_equality()
|
||||
# (fixed by the patch for MDEV-29363)
|
||||
#
|
||||
CREATE VIEW v1 AS SELECT 1 AS a;
|
||||
SELECT * FROM v1 GROUP BY a HAVING a = 'b' AND a = (a IS NULL);
|
||||
a
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect DECIMAL value: 'b'
|
||||
DROP VIEW v1;
|
||||
#
|
||||
# MDEV-32304: Pushdown: server crashes at Item_field::used_tables()
|
||||
# (fixed by the patch for MDEV-29363)
|
||||
#
|
||||
CREATE VIEW v1 AS SELECT 1 AS a;
|
||||
SELECT * FROM v1
|
||||
GROUP BY a HAVING a = (a IS NULL OR a IS NULL);
|
||||
a
|
||||
DROP VIEW v1;
|
||||
End of 10.5 tests
|
||||
|
|
|
@ -1498,3 +1498,64 @@ SELECT a FROM t1 GROUP BY a HAVING NOT a;
|
|||
DROP TABLE t1;
|
||||
|
||||
--echo End of 10.4 tests
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-29363: Constant subquery causing a crash in pushdown optimization
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (a INT, b INT, c INT);
|
||||
INSERT INTO t1 VALUES (3, 3, 4), (NULL, NULL, 2);
|
||||
|
||||
let $q=
|
||||
SELECT a,b,c FROM t1 GROUP BY a,b,c
|
||||
HAVING a = (SELECT MIN(b) AS min_b FROM t1) and (a = b or a = c);
|
||||
|
||||
eval EXPLAIN FORMAT=JSON $q;
|
||||
eval $q;
|
||||
|
||||
let $q=
|
||||
SELECT a FROM t1 GROUP BY a,b
|
||||
HAVING a = (SELECT MIN(a) AS min_a FROM t1) AND (a = 3 or a > b);
|
||||
|
||||
eval EXPLAIN FORMAT=JSON $q;
|
||||
eval $q;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-32424: Pushdown: server crashes at JOIN::save_explain_data()
|
||||
--echo # (fixed by the patch for MDEV-29363)
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (a INT, b INT, c INT);
|
||||
INSERT INTO t1 VALUES (1, 1, 3), (3, 2, 3);
|
||||
|
||||
SELECT a,b,c FROM t1 GROUP BY a,b,c
|
||||
HAVING a = (SELECT MIN(b) AS min_b FROM t1) and a IN (b, c);
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-32293: Pushdown: server crashes at check_simple_equality()
|
||||
--echo # (fixed by the patch for MDEV-29363)
|
||||
--echo #
|
||||
|
||||
CREATE VIEW v1 AS SELECT 1 AS a;
|
||||
|
||||
SELECT * FROM v1 GROUP BY a HAVING a = 'b' AND a = (a IS NULL);
|
||||
|
||||
DROP VIEW v1;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-32304: Pushdown: server crashes at Item_field::used_tables()
|
||||
--echo # (fixed by the patch for MDEV-29363)
|
||||
--echo #
|
||||
|
||||
CREATE VIEW v1 AS SELECT 1 AS a;
|
||||
|
||||
SELECT * FROM v1
|
||||
GROUP BY a HAVING a = (a IS NULL OR a IS NULL);
|
||||
|
||||
DROP VIEW v1;
|
||||
|
||||
--echo End of 10.5 tests
|
||||
|
|
11
sql/item.cc
11
sql/item.cc
|
@ -11085,8 +11085,13 @@ bool Item::cleanup_excluding_immutables_processor (void *arg)
|
|||
if (!(get_extraction_flag() == IMMUTABLE_FL))
|
||||
return cleanup_processor(arg);
|
||||
else
|
||||
{
|
||||
clear_extraction_flag();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Item::remove_immutable_flag_processor (void *arg)
|
||||
{
|
||||
if (get_extraction_flag() == IMMUTABLE_FL)
|
||||
clear_extraction_flag();
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1990,6 +1990,7 @@ public:
|
|||
virtual bool change_context_processor(void *arg) { return 0; }
|
||||
virtual bool reset_query_id_processor(void *arg) { return 0; }
|
||||
virtual bool is_expensive_processor(void *arg) { return 0; }
|
||||
bool remove_immutable_flag_processor (void *arg);
|
||||
|
||||
// FIXME reduce the number of "add field to bitmap" processors
|
||||
virtual bool add_field_to_set_processor(void *arg) { return 0; }
|
||||
|
|
|
@ -11338,6 +11338,19 @@ Item *st_select_lex::pushdown_from_having_into_where(THD *thd, Item *having)
|
|||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Remove IMMUTABLE_FL only after all of the elements of the condition are processed.
|
||||
*/
|
||||
it.rewind();
|
||||
while ((item=it++))
|
||||
{
|
||||
if (item->walk(&Item::remove_immutable_flag_processor, 0, STOP_PTR))
|
||||
{
|
||||
attach_to_conds.empty();
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
exit:
|
||||
thd->lex->current_select= save_curr_select;
|
||||
return having;
|
||||
|
|
Loading…
Reference in a new issue