diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index 57f21a5e0eb..32f7d61319b 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -2493,3 +2493,17 @@ SELECT i2 FROM t1 AS t1a STRAIGHT_JOIN ( t2 INNER JOIN t1 AS t1b ON (t1b.c1 = c2 WHERE t1a.c1 = c2 GROUP BY i2; i2 DROP TABLE t1,t2; +# +# MDEV-6855 +# MIN(*) with subqueries with IS NOT NULL in WHERE clause crashed. +# +CREATE TABLE t1 (i INT, c VARCHAR(3), KEY(c,i)) ENGINE=MyISAM; +INSERT INTO t1 VALUES (7,'foo'),(0,'bar'); +CREATE TABLE t2 (j INT) ENGINE=MyISAM; +INSERT INTO t2 VALUES (0),(8),(1),(8),(9); +SELECT MAX(i), c FROM t1 +WHERE c != 'qux' AND ( SELECT SUM(j) FROM t1, t2 ) IS NOT NULL GROUP BY c; +MAX(i) c +0 bar +7 foo +drop table t1,t2; diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test index 92d1c18ee13..a1f7f693c21 100644 --- a/mysql-test/t/group_by.test +++ b/mysql-test/t/group_by.test @@ -1665,6 +1665,21 @@ WHERE t1a.c1 = c2 GROUP BY i2; DROP TABLE t1,t2; +--echo # +--echo # MDEV-6855 +--echo # MIN(*) with subqueries with IS NOT NULL in WHERE clause crashed. +--echo # + +CREATE TABLE t1 (i INT, c VARCHAR(3), KEY(c,i)) ENGINE=MyISAM; +INSERT INTO t1 VALUES (7,'foo'),(0,'bar'); + +CREATE TABLE t2 (j INT) ENGINE=MyISAM; +INSERT INTO t2 VALUES (0),(8),(1),(8),(9); + +SELECT MAX(i), c FROM t1 +WHERE c != 'qux' AND ( SELECT SUM(j) FROM t1, t2 ) IS NOT NULL GROUP BY c; +drop table t1,t2; + # # End of MariaDB 5.5 tests # diff --git a/sql/item.h b/sql/item.h index 57e91e5b3d8..ed50605ef7b 100644 --- a/sql/item.h +++ b/sql/item.h @@ -4038,7 +4038,7 @@ private: /** @todo Implement the is_null() method for this class. Currently calling is_null() - on any Item_cache object resolves to Item::is_null(), which reutns FALSE + on any Item_cache object resolves to Item::is_null(), which returns FALSE for any value. */ diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 04481b39d2f..17b24aa70fd 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -12539,12 +12539,13 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time) SYNOPSIS check_group_min_max_predicates() - cond [in] the expression tree being analyzed - min_max_arg [in] the field referenced by the MIN/MAX function(s) - image_type [in] - has_min_max_arg [out] true if the subtree being analyzed references min_max_arg - has_other_arg [out] true if the subtree being analyzed references a column - other min_max_arg + cond [in] the expression tree being analyzed + min_max_arg [in] the field referenced by the MIN/MAX function(s) + image_type [in] + has_min_max_arg [out] true if the subtree being analyzed references + min_max_arg + has_other_arg [out] true if the subtree being analyzed references a + column other min_max_arg DESCRIPTION The function walks recursively over the cond tree representing a WHERE @@ -12588,7 +12589,7 @@ check_group_min_max_predicates(Item *cond, Item_field *min_max_arg_item, (2) the subtree passes the test, but it is an OR and it references both the min/max argument and other columns. */ - if (!check_group_min_max_predicates(and_or_arg, min_max_arg_item, //1 + if (!check_group_min_max_predicates(and_or_arg, min_max_arg_item, //1 image_type, &has_min_max, &has_other) || (func_type == Item_func::COND_OR_FUNC && has_min_max && has_other))//2 @@ -12604,7 +12605,7 @@ check_group_min_max_predicates(Item *cond, Item_field *min_max_arg_item, a subquery in the WHERE clause. */ - if (cond_type == Item::SUBSELECT_ITEM) + if (unlikely(cond_type == Item::SUBSELECT_ITEM)) { Item_subselect *subs_cond= (Item_subselect*) cond; if (subs_cond->is_correlated) @@ -12621,7 +12622,14 @@ check_group_min_max_predicates(Item *cond, Item_field *min_max_arg_item, } DBUG_RETURN(TRUE); } - + /* + Subquery with IS [NOT] NULL + TODO: Look into the cache_item and optimize it like we do for + subselect's above + */ + if (unlikely(cond_type == Item::CACHE_ITEM)) + DBUG_RETURN(cond->const_item()); + /* Condition of the form 'field' is equivalent to 'field <> 0' and thus satisfies the SA3 condition. @@ -12638,7 +12646,9 @@ check_group_min_max_predicates(Item *cond, Item_field *min_max_arg_item, /* We presume that at this point there are no other Items than functions. */ DBUG_ASSERT(cond_type == Item::FUNC_ITEM); - + if (unlikely(cond_type != Item::FUNC_ITEM)) /* Safety */ + DBUG_RETURN(FALSE); + /* Test if cond references only group-by or non-group fields. */ Item_func *pred= (Item_func*) cond; Item_func::Functype pred_type= pred->functype();