Commit d072a296 authored by Galina Shalygina's avatar Galina Shalygina

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>
parent 001608de
......@@ -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);
......
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