Commit 41541a7c authored by Igor Babaev's avatar Igor Babaev

MDEV-21683 Server crashes in get_quick_keys with not_null_range_scan

ANding of the range built from inferred NOT NULL conditions and the range
built from other conditions used in WHERE/ON clauses may produce an
IMPOSSIBLE range. The code of MDEV-15777 did not take into account this
possibility.
parent 83e75b39
...@@ -3116,7 +3116,6 @@ drop table t1,ten,t2; ...@@ -3116,7 +3116,6 @@ drop table t1,ten,t2;
# #
# MDEV-15777: Use inferred IS NOT NULL predicates in the range optimizer # MDEV-15777: Use inferred IS NOT NULL predicates in the range optimizer
# #
set @save_optimizer_switch= @@optimizer_switch;
set @@optimizer_switch='not_null_range_scan=on'; set @@optimizer_switch='not_null_range_scan=on';
create table ten(a int); create table ten(a int);
insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
...@@ -3404,6 +3403,25 @@ drop table t1,t2; ...@@ -3404,6 +3403,25 @@ drop table t1,t2;
drop table ten,one_k; drop table ten,one_k;
set @@optimizer_switch= @save_optimizer_switch; set @@optimizer_switch= @save_optimizer_switch;
# #
# MDEV-21683: ANDing of the range from inferred NOT NULL condition and
# the range from other conditions produces IMPOSSIBLE range
#
SET @save_optimizer_switch= @@optimizer_switch;
CREATE TABLE t1 (a INT, KEY(a));
INSERT INTO t1 VALUES (8),(9);
CREATE TABLE t2 (pk INT, b INT, PRIMARY KEY(pk));
INSERT INTO t2 VALUES (1,1),(2,2);
SET optimizer_switch = 'not_null_range_scan=on';
EXPLAIN EXTENDED SELECT * FROM t1 LEFT JOIN t2 ON a = pk WHERE b >= 0 AND pk IS NULL;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
Warnings:
Note 1003 select NULL AS `a`,0 AS `pk`,NULL AS `b` from `test`.`t1` join `test`.`t2` where 0
SELECT * FROM t1 LEFT JOIN t2 ON a = pk WHERE b >= 0 AND pk IS NULL;
a pk b
DROP TABLE t1, t2;
SET @@optimizer_switch= @save_optimizer_switch;
#
# End of 10.5 tests # End of 10.5 tests
# #
set global innodb_stats_persistent= @innodb_stats_persistent_save; set global innodb_stats_persistent= @innodb_stats_persistent_save;
......
...@@ -2106,7 +2106,6 @@ drop table t1,ten,t2; ...@@ -2106,7 +2106,6 @@ drop table t1,ten,t2;
--echo # MDEV-15777: Use inferred IS NOT NULL predicates in the range optimizer --echo # MDEV-15777: Use inferred IS NOT NULL predicates in the range optimizer
--echo # --echo #
set @save_optimizer_switch= @@optimizer_switch;
set @@optimizer_switch='not_null_range_scan=on'; set @@optimizer_switch='not_null_range_scan=on';
create table ten(a int); create table ten(a int);
insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
...@@ -2280,6 +2279,29 @@ drop table t1,t2; ...@@ -2280,6 +2279,29 @@ drop table t1,t2;
drop table ten,one_k; drop table ten,one_k;
set @@optimizer_switch= @save_optimizer_switch; set @@optimizer_switch= @save_optimizer_switch;
--echo #
--echo # MDEV-21683: ANDing of the range from inferred NOT NULL condition and
--echo # the range from other conditions produces IMPOSSIBLE range
--echo #
SET @save_optimizer_switch= @@optimizer_switch;
CREATE TABLE t1 (a INT, KEY(a));
INSERT INTO t1 VALUES (8),(9);
CREATE TABLE t2 (pk INT, b INT, PRIMARY KEY(pk));
INSERT INTO t2 VALUES (1,1),(2,2);
SET optimizer_switch = 'not_null_range_scan=on';
let $q=
SELECT * FROM t1 LEFT JOIN t2 ON a = pk WHERE b >= 0 AND pk IS NULL;
eval EXPLAIN EXTENDED $q;
eval $q;
DROP TABLE t1, t2;
SET @@optimizer_switch= @save_optimizer_switch;
--echo # --echo #
--echo # End of 10.5 tests --echo # End of 10.5 tests
--echo # --echo #
......
...@@ -3113,7 +3113,6 @@ drop table t1,ten,t2; ...@@ -3113,7 +3113,6 @@ drop table t1,ten,t2;
# #
# MDEV-15777: Use inferred IS NOT NULL predicates in the range optimizer # MDEV-15777: Use inferred IS NOT NULL predicates in the range optimizer
# #
set @save_optimizer_switch= @@optimizer_switch;
set @@optimizer_switch='not_null_range_scan=on'; set @@optimizer_switch='not_null_range_scan=on';
create table ten(a int); create table ten(a int);
insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
...@@ -3401,6 +3400,25 @@ drop table t1,t2; ...@@ -3401,6 +3400,25 @@ drop table t1,t2;
drop table ten,one_k; drop table ten,one_k;
set @@optimizer_switch= @save_optimizer_switch; set @@optimizer_switch= @save_optimizer_switch;
# #
# MDEV-21683: ANDing of the range from inferred NOT NULL condition and
# the range from other conditions produces IMPOSSIBLE range
#
SET @save_optimizer_switch= @@optimizer_switch;
CREATE TABLE t1 (a INT, KEY(a));
INSERT INTO t1 VALUES (8),(9);
CREATE TABLE t2 (pk INT, b INT, PRIMARY KEY(pk));
INSERT INTO t2 VALUES (1,1),(2,2);
SET optimizer_switch = 'not_null_range_scan=on';
EXPLAIN EXTENDED SELECT * FROM t1 LEFT JOIN t2 ON a = pk WHERE b >= 0 AND pk IS NULL;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
Warnings:
Note 1003 select NULL AS `a`,0 AS `pk`,NULL AS `b` from `test`.`t1` join `test`.`t2` where 0
SELECT * FROM t1 LEFT JOIN t2 ON a = pk WHERE b >= 0 AND pk IS NULL;
a pk b
DROP TABLE t1, t2;
SET @@optimizer_switch= @save_optimizer_switch;
#
# End of 10.5 tests # End of 10.5 tests
# #
set global innodb_stats_persistent= @innodb_stats_persistent_save; set global innodb_stats_persistent= @innodb_stats_persistent_save;
......
...@@ -2838,12 +2838,15 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, ...@@ -2838,12 +2838,15 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
if (notnull_cond) if (notnull_cond)
notnull_cond_tree= notnull_cond->get_mm_tree(&param, &notnull_cond); notnull_cond_tree= notnull_cond->get_mm_tree(&param, &notnull_cond);
if (cond) if (cond || notnull_cond_tree)
{ {
{ {
Json_writer_array trace_range_summary(thd, Json_writer_array trace_range_summary(thd,
"setup_range_conditions"); "setup_range_conditions");
tree= cond->get_mm_tree(&param, &cond); if (cond)
tree= cond->get_mm_tree(&param, &cond);
if (notnull_cond_tree)
tree= tree_and(&param, tree, notnull_cond_tree);
} }
if (tree) if (tree)
{ {
...@@ -2865,7 +2868,6 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, ...@@ -2865,7 +2868,6 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
} }
} }
} }
tree= tree_and(&param, tree, notnull_cond_tree);
/* /*
Try to construct a QUICK_GROUP_MIN_MAX_SELECT. Try to construct a QUICK_GROUP_MIN_MAX_SELECT.
......
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