Skip to content

Commit a68e74b

Browse files
committed
MDEV-35164: optimizer_join_limit_pref_ratio: assertion when the ORDER BY table becomes constant
Assertion failure has happened due to this scenario: A query was ran with optimizer_join_limit_pref_ratio=1. The query had "ORDER BY t1.col LIMIT N". The optimizer set join->limit_shortcut_applicable=1. Then, table t1 was marked as constant. The code in choose_query_plan() still set join->limit_optimization_mode=1 which caused the optimizer to only consider t1 as the first non-const table. But t1 was already put into the join prefix as the constant table. The optimizer couldn't produce any join order at all and crashed. Fixed by not searching for shortcut plan if ORDER BY table is a constant. We will not try to do sorting anyway in this case (and LIMIT short-cutting will be done for any join order).
1 parent 0540eac commit a68e74b

File tree

3 files changed

+81
-3
lines changed

3 files changed

+81
-3
lines changed

mysql-test/main/order_by_limit_join.result

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,32 @@ JS
457457
]
458458
set optimizer_search_depth=@tmp_osd;
459459
set optimizer_trace=@tmp_os;
460+
# An extra testcase for MDEV-35164 (its main testcase is below).
461+
alter table t1 add unique key(col2);
462+
insert into t10 select * from t10;
463+
insert into t10 select * from t10;
464+
analyze table t10;
465+
Table Op Msg_type Msg_text
466+
test.t10 analyze status Engine-independent statistics collected
467+
test.t10 analyze status OK
468+
# This will not crash and also show that sorting is not done when
469+
# ORDER BY only refers to const table columns:
470+
explain
471+
select
472+
*
473+
from
474+
t1
475+
join t10 on t1.a=t10.a
476+
join t11 on t1.b=t11.b
477+
where
478+
t1.col2=3
479+
order by
480+
t1.col1
481+
limit 10;
482+
id select_type table type possible_keys key key_len ref rows Extra
483+
1 SIMPLE t1 const col2,a,b col2 5 const 1
484+
1 SIMPLE t11 ref b b 5 const 1
485+
1 SIMPLE t10 ref a a 5 const 2
460486
drop table t1, t10, t11;
461487
#
462488
# MDEV-35072: Assertion failure with optimizer_join_limit_pref_ratio and 1-table select
@@ -468,4 +494,15 @@ SELECT * FROM t1 ORDER BY c1 LIMIT 1;
468494
c1
469495
1
470496
DROP TABLE t1;
497+
#
498+
# MDEV-35164: optimizer_join_limit_pref_ratio: assertion when the ORDER BY table becomes constant
499+
# Original testcase:
500+
#
501+
SET optimizer_join_limit_pref_ratio=1;
502+
CREATE TABLE t1 (a INT KEY,b INT, KEY(b)) ;
503+
INSERT INTO t1 VALUES (2,NULL);
504+
INSERT INTO t1 VALUES (5,NULL);
505+
SELECT * FROM t1 NATURAL JOIN t1 AS t2 WHERE t1.b=NULL ORDER BY t1.a LIMIT 1;
506+
a b
507+
DROP TABLE t1;
471508
set optimizer_join_limit_pref_ratio=default;

mysql-test/main/order_by_limit_join.test

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,9 +205,29 @@ set @trace=(select trace from information_schema.optimizer_trace);
205205
--source include/optimizer_trace_no_costs.inc
206206
select json_detailed(json_extract(@trace, '$**.join_limit_shortcut_choice')) as JS;
207207

208-
209208
set optimizer_search_depth=@tmp_osd;
210209
set optimizer_trace=@tmp_os;
210+
211+
--echo # An extra testcase for MDEV-35164 (its main testcase is below).
212+
alter table t1 add unique key(col2);
213+
insert into t10 select * from t10;
214+
insert into t10 select * from t10;
215+
analyze table t10;
216+
217+
--echo # This will not crash and also show that sorting is not done when
218+
--echo # ORDER BY only refers to const table columns:
219+
explain
220+
select
221+
*
222+
from
223+
t1
224+
join t10 on t1.a=t10.a
225+
join t11 on t1.b=t11.b
226+
where
227+
t1.col2=3
228+
order by
229+
t1.col1
230+
limit 10;
211231
drop table t1, t10, t11;
212232

213233
--echo #
@@ -219,4 +239,15 @@ INSERT INTO t1 VALUES (1),(2);
219239
SELECT * FROM t1 ORDER BY c1 LIMIT 1;
220240
DROP TABLE t1;
221241

242+
--echo #
243+
--echo # MDEV-35164: optimizer_join_limit_pref_ratio: assertion when the ORDER BY table becomes constant
244+
--echo # Original testcase:
245+
--echo #
246+
SET optimizer_join_limit_pref_ratio=1;
247+
CREATE TABLE t1 (a INT KEY,b INT, KEY(b)) ;
248+
INSERT INTO t1 VALUES (2,NULL);
249+
INSERT INTO t1 VALUES (5,NULL);
250+
SELECT * FROM t1 NATURAL JOIN t1 AS t2 WHERE t1.b=NULL ORDER BY t1.a LIMIT 1;
251+
DROP TABLE t1;
252+
222253
set optimizer_join_limit_pref_ratio=default;

sql/sql_select.cc

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9306,8 +9306,18 @@ choose_plan(JOIN *join, table_map join_tables)
93069306
double limit_cost= DBL_MAX;
93079307
POSITION *limit_plan= NULL;
93089308

9309-
/* First, build a join plan that can short-cut ORDER BY...LIMIT */
9310-
if (join->limit_shortcut_applicable && !join->emb_sjm_nest)
9309+
/*
9310+
First, build a join plan that can short-cut ORDER BY...LIMIT.
9311+
Do it if
9312+
(1) The SELECT in query makes it possible to do short-cutting for
9313+
some table TBL.
9314+
(2) We are optimizing the whole JOIN, not a semi-join nest
9315+
(3) The table TBL has not been marked as constant (in this case,
9316+
ORDER BY LIMIT will be optimized away)
9317+
*/
9318+
if (join->limit_shortcut_applicable && // (1)
9319+
!join->emb_sjm_nest && // (2)
9320+
!(join->sort_by_table->map & join->const_table_map)) //(3)
93119321
{
93129322
bool res;
93139323
Json_writer_object wrapper(join->thd);

0 commit comments

Comments
 (0)