diff --git a/mysql-test/r/index_merge_myisam.result b/mysql-test/r/index_merge_myisam.result index 0b6959d15a9..e771d48b6d2 100644 --- a/mysql-test/r/index_merge_myisam.result +++ b/mysql-test/r/index_merge_myisam.result @@ -1617,4 +1617,30 @@ GROUP BY 2; COUNT(DISTINCT t2.b) CONCAT(t1.c) 2 0 DROP TABLE t1,t2,t3; +# +# MDEV-4556 Server crashes in SEL_ARG::rb_insert with index_merge+index_merge_sort_union, FORCE INDEX +# +CREATE TABLE t1 ( +pk int, +code char(2), +population_rate int, +area_rate int, +primary key (pk), +index (code), +key (population_rate), +key (area_rate) +); +INSERT INTO t1 VALUES (1,'WI',20, 23), (2, 'WA', 13, 18); +EXPLAIN +SELECT * FROM t1 FORCE INDEX ( PRIMARY, population_rate, area_rate, code ) +WHERE pk = 1 OR population_rate = 1 OR ( area_rate IN ( 1,2 ) OR area_rate IS NULL ) +AND (population_rate = 25 OR area_rate BETWEEN 2 AND 25 OR code BETWEEN 'MA' AND 'TX'); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index_merge PRIMARY,code,population_rate,area_rate PRIMARY,population_rate,area_rate 4,5,5 NULL 2 Using sort_union(PRIMARY,population_rate,area_rate); Using where +SELECT * FROM t1 FORCE INDEX ( PRIMARY, population_rate, area_rate, code ) +WHERE pk = 1 OR population_rate = 1 OR ( area_rate IN ( 1,2 ) OR area_rate IS NULL ) +AND (population_rate = 25 OR area_rate BETWEEN 2 AND 25 OR code BETWEEN 'MA' AND 'TX'); +pk code population_rate area_rate +1 WI 20 23 +DROP TABLE t1; set optimizer_switch= @optimizer_switch_save; diff --git a/mysql-test/t/index_merge_myisam.test b/mysql-test/t/index_merge_myisam.test index 614c6595d61..07f83fa6713 100644 --- a/mysql-test/t/index_merge_myisam.test +++ b/mysql-test/t/index_merge_myisam.test @@ -149,5 +149,32 @@ GROUP BY 2; DROP TABLE t1,t2,t3; +--echo # +--echo # MDEV-4556 Server crashes in SEL_ARG::rb_insert with index_merge+index_merge_sort_union, FORCE INDEX +--echo # +CREATE TABLE t1 ( + pk int, + code char(2), + population_rate int, + area_rate int, + primary key (pk), + index (code), + key (population_rate), + key (area_rate) +); + +INSERT INTO t1 VALUES (1,'WI',20, 23), (2, 'WA', 13, 18); + +EXPLAIN +SELECT * FROM t1 FORCE INDEX ( PRIMARY, population_rate, area_rate, code ) +WHERE pk = 1 OR population_rate = 1 OR ( area_rate IN ( 1,2 ) OR area_rate IS NULL ) +AND (population_rate = 25 OR area_rate BETWEEN 2 AND 25 OR code BETWEEN 'MA' AND 'TX'); + +SELECT * FROM t1 FORCE INDEX ( PRIMARY, population_rate, area_rate, code ) +WHERE pk = 1 OR population_rate = 1 OR ( area_rate IN ( 1,2 ) OR area_rate IS NULL ) +AND (population_rate = 25 OR area_rate BETWEEN 2 AND 25 OR code BETWEEN 'MA' AND 'TX'); + +DROP TABLE t1; + set optimizer_switch= @optimizer_switch_save; diff --git a/sql/opt_range.cc b/sql/opt_range.cc index bcd522c8065..239d4411188 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -4916,6 +4916,8 @@ TABLE_READ_PLAN *merge_same_index_scans(PARAM *param, SEL_IMERGE *imerge, bzero((*changed_tree)->keys, sizeof((*changed_tree)->keys[0])*param->keys); (*changed_tree)->keys_map.clear_all(); + key->incr_refs(); + (*tree)->keys[key_idx]->incr_refs(); if (((*changed_tree)->keys[key_idx]= key_or(param, key, (*tree)->keys[key_idx]))) (*changed_tree)->keys_map.set_bit(key_idx);