summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Petrunia <psergey@askmonty.org>2021-01-30 00:54:21 +0300
committerSergei Petrunia <psergey@askmonty.org>2021-01-30 00:54:21 +0300
commit73c43ee9ed067dd22a85f7f8241e33b14be7dd37 (patch)
tree21849e56dbe6c8de5d3627cecc6686eb877b5588
parenta70a47f2f33ddb1b0e2e4ada31c63990b0512114 (diff)
downloadmariadb-git-73c43ee9ed067dd22a85f7f8241e33b14be7dd37.tar.gz
MDEV-24739: Assertion `root->weight >= ...' failed in SEL_ARG::tree_delete
Also update the SEL_ARG graph weight in: - sel_add() - SEL_ARG::clone() Make key_{and,or}_with_limit() to also verify weight for the arguments (There is no single point to verify SEL_ARG graphs constructed from conditions that are not AND-OR formulas, so we hope that those are connected with AND/OR and do it here).
-rw-r--r--mysql-test/main/range_notembedded.result11
-rw-r--r--mysql-test/main/range_notembedded.test13
-rw-r--r--sql/opt_range.cc29
3 files changed, 53 insertions, 0 deletions
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;
}
@@ -9036,6 +9037,19 @@ SEL_ARG *Field::stored_field_make_mm_leaf_exact(RANGE_OPT_PARAM *param,
******************************************************************************/
/*
+ 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