diff --git a/mysql-test/main/range_notembedded.result b/mysql-test/main/range_notembedded.result index 1f6db102624..87fa85d3ac6 100644 --- a/mysql-test/main/range_notembedded.result +++ b/mysql-test/main/range_notembedded.result @@ -214,3 +214,14 @@ left(@json, 1500) set optimizer_max_sel_arg_weight= @tmp9750_weight; set optimizer_trace=@tmp_9750; drop table t1; +# +# MDEV-24739: Assertion `root->weight >= ...' failed in SEL_ARG::tree_delete +# +SELECT * +FROM mysql.help_relation +WHERE NOT (help_topic_id != 8 AND help_keyword_id != 0 OR help_keyword_id = 2 OR help_topic_id < 1900); +help_topic_id help_keyword_id +SELECT * +FROM mysql.help_relation ignore index (help_topic_id) +WHERE (help_topic_id = 8 OR help_keyword_id = 0) AND help_keyword_id != 2 AND help_topic_id >= 1900; +help_topic_id help_keyword_id diff --git a/mysql-test/main/range_notembedded.test b/mysql-test/main/range_notembedded.test index d50bec23148..a70749ced6b 100644 --- a/mysql-test/main/range_notembedded.test +++ b/mysql-test/main/range_notembedded.test @@ -96,4 +96,17 @@ select left(@json, 1500); set optimizer_max_sel_arg_weight= @tmp9750_weight; set optimizer_trace=@tmp_9750; + drop table t1; + +--echo # +--echo # MDEV-24739: Assertion `root->weight >= ...' failed in SEL_ARG::tree_delete +--echo # +SELECT * +FROM mysql.help_relation +WHERE NOT (help_topic_id != 8 AND help_keyword_id != 0 OR help_keyword_id = 2 OR help_topic_id < 1900); + +SELECT * +FROM mysql.help_relation ignore index (help_topic_id) +WHERE (help_topic_id = 8 OR help_keyword_id = 0) AND help_keyword_id != 2 AND help_topic_id >= 1900; + diff --git a/sql/opt_range.cc b/sql/opt_range.cc index e04a1e2753f..28a8809beec 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -2079,6 +2079,7 @@ SEL_ARG *SEL_ARG::clone(RANGE_OPT_PARAM *param, SEL_ARG *new_parent, tmp->color= color; tmp->elements= this->elements; tmp->max_part_no= max_part_no; + tmp->weight= weight; return tmp; } @@ -9035,6 +9036,19 @@ SEL_ARG *Field::stored_field_make_mm_leaf_exact(RANGE_OPT_PARAM *param, ** KEY_RANGE: Condition uses a key ******************************************************************************/ +/* + Update weights for SEL_ARG graph that is connected only via next_key_part + (and not left/right) links +*/ +static uint update_weight_for_single_arg(SEL_ARG *arg) +{ + if (arg->next_key_part) + return (arg->weight= 1 + update_weight_for_single_arg(arg->next_key_part)); + else + return (arg->weight= 1); +} + + /* Add a new key test to a key when scanning through all keys This will never be called for same key parts. @@ -9067,6 +9081,8 @@ sel_add(SEL_ARG *key1,SEL_ARG *key2) } } *key_link=key1 ? key1 : key2; + + update_weight_for_single_arg(root); return root; } @@ -10020,6 +10036,13 @@ static SEL_ARG *key_or_with_limit(RANGE_OPT_PARAM *param, uint keyno, SEL_ARG *key1, SEL_ARG *key2) { +#ifndef DBUG_OFF + if (key1) + key1->verify_weight(); + if (key2) + key2->verify_weight(); +#endif + SEL_ARG *res= key_or(param, key1, key2); res= enforce_sel_arg_weight_limit(param, keyno, res); #ifndef DBUG_OFF @@ -10034,6 +10057,12 @@ static SEL_ARG *key_and_with_limit(RANGE_OPT_PARAM *param, uint keyno, SEL_ARG *key1, SEL_ARG *key2, uint clone_flag) { +#ifndef DBUG_OFF + if (key1) + key1->verify_weight(); + if (key2) + key2->verify_weight(); +#endif SEL_ARG *res= key_and(param, key1, key2, clone_flag); res= enforce_sel_arg_weight_limit(param, keyno, res); #ifndef DBUG_OFF