diff --git a/mysql-test/r/skip_records_in_range.result b/mysql-test/r/skip_records_in_range.result index e9a622f52f3..18fa3a3bdb9 100644 --- a/mysql-test/r/skip_records_in_range.result +++ b/mysql-test/r/skip_records_in_range.result @@ -528,3 +528,19 @@ select * from v1; v3 DROP VIEW v1; DROP TABLE t1; +# +# Bug #117750: FORCE INDEX does not skip records_in_range() for 'x IS NOT NULL' +# +CREATE TABLE t1 (c1 INT, KEY (c1)); +INSERT INTO t1 VALUES (1), (2), (3), (4), (5), (6), (7), (8), (NULL), (NULL); +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +set debug='+d,crash_records_in_range'; +EXPLAIN SELECT * FROM t1 FORCE INDEX(c1) WHERE c1 IS NOT NULL; +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 NULL range c1 c1 5 NULL 1 100.00 Using where; Using index +Warnings: +Note 1003 /* select#1 */ select `test`.`t1`.`c1` AS `c1` from `test`.`t1` FORCE INDEX (`c1`) where (`test`.`t1`.`c1` is not null) +set debug='-d,crash_records_in_range'; +DROP TABLE t1; diff --git a/mysql-test/t/skip_records_in_range.test b/mysql-test/t/skip_records_in_range.test index 09da3de714f..0b3acec955c 100644 --- a/mysql-test/t/skip_records_in_range.test +++ b/mysql-test/t/skip_records_in_range.test @@ -116,3 +116,19 @@ eval $query1; DROP VIEW v1; DROP TABLE t1; + +--echo # +--echo # Bug 117750#: FORCE INDEX does not skip records_in_range() for 'x IS NOT NULL' +--echo # + +CREATE TABLE t1 (c1 INT, KEY (c1)); +INSERT INTO t1 VALUES (1), (2), (3), (4), (5), (6), (7), (8), (NULL), (NULL); +ANALYZE TABLE t1; + +set debug='+d,crash_records_in_range'; + +EXPLAIN SELECT * FROM t1 FORCE INDEX(c1) WHERE c1 IS NOT NULL; + +set debug='-d,crash_records_in_range'; + +DROP TABLE t1; diff --git a/sql/range_optimizer/tree.h b/sql/range_optimizer/tree.h index 2d1eaf83653..71ae273046a 100644 --- a/sql/range_optimizer/tree.h +++ b/sql/range_optimizer/tree.h @@ -579,7 +579,9 @@ class SEL_ARG { inline void merge_flags(SEL_ARG *arg) { maybe_flag |= arg->maybe_flag; } inline void maybe_smaller() { maybe_flag = true; } /* Return true iff it's a single-point null interval */ - inline bool is_null_interval() { return maybe_null() && max_value[0] == 1; } + inline bool is_null_interval() { + return !(max_flag & NO_MAX_RANGE) && maybe_null() && max_value[0] == 1; + } inline int cmp_min_to_min(const SEL_ARG *arg) const { return sel_cmp(field, min_value, arg->min_value, min_flag, arg->min_flag); }