Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 75 additions & 3 deletions mysql-test/main/range_notembedded.result
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ left(@json, 2500)
"sel_arg_weight_heuristic":
{
"key1_field": "kp1",
"key2_field": "kp2",
"key2_type": 3,
"key1_weight": 10,
"key2_weight": 10
}
Expand All @@ -133,7 +133,7 @@ left(@json, 2500)
"sel_arg_weight_heuristic":
{
"key1_field": "kp1",
"key2_field": "kp3",
"key2_type": 3,
"key1_weight": 10,
"key2_weight": 10
}
Expand All @@ -142,7 +142,7 @@ left(@json, 2500)
"sel_arg_weight_heuristic":
{
"key1_field": "kp1",
"key2_field": "kp4",
"key2_type": 3,
"key1_weight": 10,
"key2_weight": 10
}
Expand Down Expand Up @@ -308,3 +308,75 @@ json_pretty(json_search(@trace, 'all', 'key1'))
"$[0].analyzing_range_alternatives.range_scan_alternatives[0].index"
]
drop table t1;
#
# MDEV-37510: Crash in sel_arg_and_weight_heuristic
#
SET @save_optimizer_trace=@@optimizer_trace;
SET @save_optimizer_max_sel_arg_weight=@@optimizer_max_sel_arg_weight;
SET optimizer_trace= 'enabled=on';
SET optimizer_max_sel_arg_weight=1;
CREATE TABLE t1 (c1 INT, c2 VARCHAR(10), c3 VARCHAR(10));
CREATE TABLE t2 (c1 INT, c2 VARCHAR(10), c3 VARCHAR(10));
INSERT INTO t1 values (2, 'two', 'prime'), (3, 'three', 'prime');
INSERT INTO t2 values (2, 'two', '2_table'), (4, 'four', '2_table');
EXPLAIN
SELECT t1.c1, v1.c2
FROM
(
t1
JOIN
(
SELECT c1, c2, c3 FROM t2
UNION SELECT c1, c2, c3 FROM t2
) v1
ON (
(t1.c1 = v1.c1 OR v1.c1 IS NULL) AND
(t1.c2 = v1.c2 OR v1.c3 IS NULL) AND
v1.c3 IN ('2_table', '3_table')
)
)
WHERE t1.c1 NOT IN (5, 6, 7);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
1 PRIMARY <derived2> ALL distinct_key NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join)
2 DERIVED t2 ALL NULL NULL NULL NULL 2 Using where
3 UNION t2 ALL NULL NULL NULL NULL 2 Using where
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL
set @trace= (select trace from information_schema.optimizer_trace);
set @json= json_detailed(json_extract(@trace, '$**.setup_range_conditions'));
select left(@json, 2500);
left(@json, 2500)
[
[
{
"sel_arg_weight_heuristic":
{
"key1_type": 2,
"key2_type": 2,
"key1_weight": 1,
"key2_weight": 1
}
},
{
"sel_arg_weight_heuristic":
{
"key1_type": 2,
"key2_type": 3,
"key1_weight": 1,
"key2_weight": 1
}
},
{
"enforce_sel_arg_weight_limit":
{
"index": "distinct_key",
"old_weight": 2,
"new_weight": 0
}
}
]
]
DROP TABLE t1, t2;
SET optimizer_trace=@save_optimizer_trace;
SET optimizer_max_sel_arg_weight=@save_optimizer_max_sel_arg_weight;
# end of 11.4 tests
42 changes: 42 additions & 0 deletions mysql-test/main/range_notembedded.test
Original file line number Diff line number Diff line change
Expand Up @@ -211,3 +211,45 @@ set @trace=json_extract((select trace from information_schema.optimizer_trace),
select json_pretty(json_search(@trace, 'all', 'key1'));
drop table t1;

--echo #
--echo # MDEV-37510: Crash in sel_arg_and_weight_heuristic
--echo #
SET @save_optimizer_trace=@@optimizer_trace;
SET @save_optimizer_max_sel_arg_weight=@@optimizer_max_sel_arg_weight;

SET optimizer_trace= 'enabled=on';
SET optimizer_max_sel_arg_weight=1;

CREATE TABLE t1 (c1 INT, c2 VARCHAR(10), c3 VARCHAR(10));
CREATE TABLE t2 (c1 INT, c2 VARCHAR(10), c3 VARCHAR(10));

INSERT INTO t1 values (2, 'two', 'prime'), (3, 'three', 'prime');
INSERT INTO t2 values (2, 'two', '2_table'), (4, 'four', '2_table');

EXPLAIN
SELECT t1.c1, v1.c2
FROM
(
t1
JOIN
(
SELECT c1, c2, c3 FROM t2
UNION SELECT c1, c2, c3 FROM t2
) v1
ON (
(t1.c1 = v1.c1 OR v1.c1 IS NULL) AND
(t1.c2 = v1.c2 OR v1.c3 IS NULL) AND
v1.c3 IN ('2_table', '3_table')
)
)
WHERE t1.c1 NOT IN (5, 6, 7);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't believe this is the minimal testcase.

Please try to reduce it as much as possible.

Tables need to have two records to avoid the "1-row table is const table" code path.

when one sees

CREATE TABLE t2 (c1 INT, c2 VARCHAR(10), c3 VARCHAR(10) DEFAULT NULL);

one wonders what is DEFAULT NULL there for? It's not needed in any case, please remove it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure

set @trace= (select trace from information_schema.optimizer_trace);
set @json= json_detailed(json_extract(@trace, '$**.setup_range_conditions'));
select left(@json, 2500);

DROP TABLE t1, t2;

SET optimizer_trace=@save_optimizer_trace;
SET optimizer_max_sel_arg_weight=@save_optimizer_max_sel_arg_weight;
--echo # end of 11.4 tests
14 changes: 9 additions & 5 deletions sql/opt_range.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11523,11 +11523,15 @@ bool sel_arg_and_weight_heuristic(RANGE_OPT_PARAM *param, SEL_ARG *key1,
{
Json_writer_object wrapper(param->thd);
Json_writer_object obj(param->thd, "sel_arg_weight_heuristic");
obj.
add("key1_field", key1->field->field_name).
add("key2_field", key2->field->field_name).
add("key1_weight", (longlong)key1->weight).
add("key2_weight", (longlong)key2->weight);

if (key1->type == SEL_ARG::KEY_RANGE)
obj.add("key1_field", key1->field->field_name);
else
obj.add("key1_type", (uint) key1->type);

obj.add("key2_type", (uint) key2->type);
obj.add("key1_weight", (longlong) key1->weight);
obj.add("key2_weight", (longlong) key2->weight);
}
return true; // Discard key2
}
Expand Down