mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +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
|
# 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 #
|
||||||
--echo # End of 10.4 tests
|
--echo # End of 10.4 tests
|
||||||
--echo #
|
--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
|
which do not use aggregate functions. In such case
|
||||||
temporary table may not be used and const condition
|
temporary table may not be used and const condition
|
||||||
elements may be lost during further having
|
elements may be lost during further having
|
||||||
condition transformation in JOIN::exec.
|
condition transformation.
|
||||||
*/
|
*/
|
||||||
if (having && const_table_map && !having->with_sum_func())
|
if (having && const_table_map && !having->with_sum_func())
|
||||||
{
|
{
|
||||||
having->update_used_tables();
|
having->update_used_tables();
|
||||||
having= having->remove_eq_conds(thd, &select_lex->having_value, true);
|
if (having->const_item() && !having->is_expensive())
|
||||||
if (select_lex->having_value == Item::COND_FALSE)
|
{
|
||||||
|
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";
|
zero_result_cause= "Impossible HAVING noticed after reading const tables";
|
||||||
error= 0;
|
error= 0;
|
||||||
select_lex->mark_const_derived(zero_result_cause);
|
select_lex->mark_const_derived(zero_result_cause);
|
||||||
goto setup_subq_exit;
|
goto setup_subq_exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (optimize_unflattened_subqueries())
|
if (optimize_unflattened_subqueries())
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
Reference in New Issue
Block a user