diff --git a/mysql-test/main/having.result b/mysql-test/main/having.result index 95497a59c20..9f8a1c6e73c 100644 --- a/mysql-test/main/having.result +++ b/mysql-test/main/having.result @@ -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 +# diff --git a/mysql-test/main/having.test b/mysql-test/main/having.test index b114070c60f..812038b2d60 100644 --- a/mysql-test/main/having.test +++ b/mysql-test/main/having.test @@ -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 # diff --git a/sql/sql_select.cc b/sql/sql_select.cc index b86ffed8619..93b53699c9a 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2971,19 +2971,22 @@ 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()) { - 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; + bool having_value= having->val_int(); + having= new (thd->mem_root) Item_bool(thd, having_value); + if (!having_value) + { + zero_result_cause= "Impossible HAVING noticed after reading const tables"; + error= 0; + select_lex->mark_const_derived(zero_result_cause); + goto setup_subq_exit; + } } }