mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
MDEV-23983: Crash caused by query containing constant having clause
Before this patch the crash occured when a single row dataset is used and Item::remove_eq_conds() is called for HAVING. This function is not supposed to be called after the elimination of multiple equalities. To fix this problem instead of Item::remove_eq_conds() Item::val_int() is used. In this case the optimizer tries to evaluate the condition for the single row dataset and discovers impossible HAVING immediately. So, the execution phase is skipped. Approved by Igor Babaev <igor@maridb.com>
This commit is contained in:
@ -955,3 +955,47 @@ DROP TABLE t;
|
||||
#
|
||||
# End of 10.4 tests
|
||||
#
|
||||
#
|
||||
# MDEV-23983: Crash caused by query containing constant having clause
|
||||
#
|
||||
CREATE TABLE t1 (id INT PRIMARY KEY, a INT, b TEXT, c INT);
|
||||
INSERT INTO t1 VALUES (3, 7, 'b', 1), (4, 7, 'b', 1);
|
||||
SELECT * FROM t1
|
||||
WHERE t1.id = 3
|
||||
GROUP BY t1.a
|
||||
HAVING t1.b = 'b' and t1.c = 1;
|
||||
id a b c
|
||||
3 7 b 1
|
||||
SELECT * FROM t1
|
||||
WHERE t1.id = 3
|
||||
GROUP BY t1.a
|
||||
HAVING t1.b = 'b' and t1.c = 2;
|
||||
id a b c
|
||||
explain SELECT * FROM t1
|
||||
WHERE t1.id = 3
|
||||
GROUP BY t1.a
|
||||
HAVING t1.b = 'b' and t1.c = 2;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible HAVING noticed after reading const tables
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a INT, b INT) ENGINE=MyISAM;
|
||||
CREATE TABLE t2 (id INT, b TEXT, c INT) ENGINE=MyISAM;
|
||||
INSERT INTO t2 VALUES (3, 'b', 1);
|
||||
SELECT t2.* FROM t2 LEFT JOIN t1 ON t2.id = t1.a
|
||||
GROUP BY t2.id
|
||||
HAVING t2.b = 'b' and t2.c = 1;
|
||||
id b c
|
||||
3 b 1
|
||||
SELECT t2.* FROM t2 LEFT JOIN t1 ON t2.id = t1.a
|
||||
GROUP BY t2.id
|
||||
HAVING t2.b = 'b' and t2.c = 2;
|
||||
id b c
|
||||
explain SELECT t2.* FROM t2 LEFT JOIN t1 ON t2.id = t1.a
|
||||
GROUP BY t2.id
|
||||
HAVING t2.b = 'b' and t2.c = 2;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible HAVING noticed after reading const tables
|
||||
DROP TABLE t1,t2;
|
||||
#
|
||||
# End of 10.5 tests
|
||||
#
|
||||
|
@ -1011,3 +1011,48 @@ DROP TABLE t;
|
||||
--echo #
|
||||
--echo # End of 10.4 tests
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-23983: Crash caused by query containing constant having clause
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (id INT PRIMARY KEY, a INT, b TEXT, c INT);
|
||||
INSERT INTO t1 VALUES (3, 7, 'b', 1), (4, 7, 'b', 1);
|
||||
|
||||
SELECT * FROM t1
|
||||
WHERE t1.id = 3
|
||||
GROUP BY t1.a
|
||||
HAVING t1.b = 'b' and t1.c = 1;
|
||||
|
||||
let $q=
|
||||
SELECT * FROM t1
|
||||
WHERE t1.id = 3
|
||||
GROUP BY t1.a
|
||||
HAVING t1.b = 'b' and t1.c = 2;
|
||||
|
||||
eval $q;
|
||||
eval explain $q;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (a INT, b INT) ENGINE=MyISAM;
|
||||
CREATE TABLE t2 (id INT, b TEXT, c INT) ENGINE=MyISAM;
|
||||
INSERT INTO t2 VALUES (3, 'b', 1);
|
||||
|
||||
SELECT t2.* FROM t2 LEFT JOIN t1 ON t2.id = t1.a
|
||||
GROUP BY t2.id
|
||||
HAVING t2.b = 'b' and t2.c = 1;
|
||||
|
||||
let $q=
|
||||
SELECT t2.* FROM t2 LEFT JOIN t1 ON t2.id = t1.a
|
||||
GROUP BY t2.id
|
||||
HAVING t2.b = 'b' and t2.c = 2;
|
||||
|
||||
eval $q;
|
||||
eval explain $q;
|
||||
|
||||
DROP TABLE t1,t2;
|
||||
|
||||
--echo #
|
||||
--echo # End of 10.5 tests
|
||||
--echo #
|
||||
|
@ -2971,21 +2971,24 @@ int JOIN::optimize_stage2()
|
||||
which do not use aggregate functions. In such case
|
||||
temporary table may not be used and const condition
|
||||
elements may be lost during further having
|
||||
condition transformation in JOIN::exec.
|
||||
condition transformation.
|
||||
*/
|
||||
if (having && const_table_map && !having->with_sum_func())
|
||||
{
|
||||
having->update_used_tables();
|
||||
having= having->remove_eq_conds(thd, &select_lex->having_value, true);
|
||||
if (select_lex->having_value == Item::COND_FALSE)
|
||||
if (having->const_item() && !having->is_expensive())
|
||||
{
|
||||
bool having_value= having->val_int();
|
||||
having= new (thd->mem_root) Item_bool(thd, having_value);
|
||||
if (!having_value)
|
||||
{
|
||||
having= new (thd->mem_root) Item_bool(thd, false);
|
||||
zero_result_cause= "Impossible HAVING noticed after reading const tables";
|
||||
error= 0;
|
||||
select_lex->mark_const_derived(zero_result_cause);
|
||||
goto setup_subq_exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (optimize_unflattened_subqueries())
|
||||
DBUG_RETURN(1);
|
||||
|
Reference in New Issue
Block a user