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; ...@@ -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; ...@@ -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,19 +2971,22 @@ int JOIN::optimize_stage2() ...@@ -2971,19 +2971,22 @@ 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)
{ {
having= new (thd->mem_root) Item_bool(thd, false); bool having_value= having->val_int();
zero_result_cause= "Impossible HAVING noticed after reading const tables"; having= new (thd->mem_root) Item_bool(thd, having_value);
error= 0; if (!having_value)
select_lex->mark_const_derived(zero_result_cause); {
goto setup_subq_exit; zero_result_cause= "Impossible HAVING noticed after reading const tables";
error= 0;
select_lex->mark_const_derived(zero_result_cause);
goto setup_subq_exit;
}
} }
} }
......
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