diff --git a/mysql-test/main/derived_view.result b/mysql-test/main/derived_view.result index 50f6d381dd6..15a7784c890 100644 --- a/mysql-test/main/derived_view.result +++ b/mysql-test/main/derived_view.result @@ -2696,7 +2696,7 @@ ON p.id = g.p_random ORDER BY gallery_name ASC ; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY ALL NULL NULL NULL NULL 10 Using temporary; Using filesort +1 PRIMARY ALL NULL NULL NULL NULL 10 Using filesort 1 PRIMARY p eq_ref PRIMARY PRIMARY 4 g.p_random 1 Using where 2 DERIVED gal ALL NULL NULL NULL NULL 10 3 DEPENDENT SUBQUERY pi ref gallery_id gallery_id 4 test.gal.id 4 Using temporary; Using filesort diff --git a/mysql-test/main/having.result b/mysql-test/main/having.result index ac26d69543d..d7cbadd5e75 100644 --- a/mysql-test/main/having.result +++ b/mysql-test/main/having.result @@ -834,13 +834,13 @@ test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK explain SELECT t, next_seq_value() r FROM t1 FORCE INDEX(t) GROUP BY t HAVING r = 1 ORDER BY t1.u; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 8 Using temporary; Using filesort +1 SIMPLE t1 index NULL t 5 NULL 8 Using temporary; Using filesort SELECT t, next_seq_value() r FROM t1 FORCE INDEX(t) GROUP BY t HAVING r = 1 ORDER BY t1.u; t r 10 1 12 1 -14 1 -16 1 +15 1 +17 1 DROP TABLE t1; DROP FUNCTION next_seq_value; DROP TABLE series; diff --git a/mysql-test/main/show_explain.result b/mysql-test/main/show_explain.result index 317a12ef311..6ad93930448 100644 --- a/mysql-test/main/show_explain.result +++ b/mysql-test/main/show_explain.result @@ -1007,7 +1007,7 @@ SELECT a+SLEEP(0.01) FROM t1 WHERE a IN ( 255, 0 ) OR b BETWEEN 6 AND 129 ORDER BY b; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index_merge a,b a,b 5,5 NULL 8 Using sort_union(a,b); Using where; Using temporary; Using filesort +1 SIMPLE t1 index_merge a,b a,b 5,5 NULL 8 Using sort_union(a,b); Using where; Using filesort set @show_explain_probe_select_id=1; SET debug_dbug='+d,show_explain_probe_join_exec_start'; SELECT a+SLEEP(0.01) FROM t1 @@ -1016,7 +1016,7 @@ ORDER BY b; connection default; show explain for $thr2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index_merge a,b a,b 5,5 NULL 8 Using sort_union(a,b); Using where; Using temporary; Using filesort +1 SIMPLE t1 index_merge a,b a,b 5,5 NULL 8 Using sort_union(a,b); Using where; Using filesort Warnings: Note 1003 SELECT a+SLEEP(0.01) FROM t1 WHERE a IN ( 255, 0 ) OR b BETWEEN 6 AND 129 @@ -1039,7 +1039,7 @@ ORDER BY b; connection default; show explain for $thr2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index_merge a,b a,b 5,5 NULL 8 Using sort_union(a,b); Using where; Using temporary; Using filesort +1 SIMPLE t1 index_merge a,b a,b 5,5 NULL 8 Using sort_union(a,b); Using where; Using filesort Warnings: Note 1003 SELECT a+SLEEP(0.01) FROM t1 WHERE a IN ( 255, 0 ) OR b BETWEEN 6 AND 129 diff --git a/mysql-test/main/sp.result b/mysql-test/main/sp.result index b14551d35c7..88df800b0e0 100644 --- a/mysql-test/main/sp.result +++ b/mysql-test/main/sp.result @@ -8932,3 +8932,43 @@ ERROR 42000: PROCEDURE does not support subqueries or stored functions DROP TABLE t1; # End of 10.4 tests # +# +# MDEV-29129: Performance regression starting in 10.6: unlimited "select order by limit" +# +CREATE TABLE t1 ( +lookupId int primary key, +value varchar(255) +); +insert into t1 select seq, seq from seq_1_to_100; +# Note: the function is intentionally NOT declared as DETERMINISTIC +CREATE FUNCTION f1(LOOKUPID_IN INT) RETURNS varchar(255) CHARSET utf8 +BEGIN +DECLARE LOOKUP_VALUE VARCHAR(255); +SET LOOKUP_VALUE = (SELECT value FROM t1 WHERE lookupId = LOOKUPID_IN); +set @counter=@counter+1; +RETURN LOOKUP_VALUE; +END; +// +create table t2 ( +col1 int, +col2 int +); +insert into t2 select mod(seq,100), seq from seq_1_to_1000; +explain +select f1(col1) from t2 order by col2 desc limit 5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 1000 Using filesort +set @counter=0; +select f1(col1) from t2 order by col2 desc limit 5; +f1(col1) +NULL +99 +98 +97 +96 +# Must show 5, not 1000: +select @counter; +@counter +5 +drop function f1; +drop table t1,t2; diff --git a/mysql-test/main/sp.test b/mysql-test/main/sp.test index b71cfe11d58..baf89eeaba5 100644 --- a/mysql-test/main/sp.test +++ b/mysql-test/main/sp.test @@ -10519,3 +10519,40 @@ DROP TABLE t1; --echo # End of 10.4 tests --echo # + +--echo # +--echo # MDEV-29129: Performance regression starting in 10.6: unlimited "select order by limit" +--echo # + +CREATE TABLE t1 ( + lookupId int primary key, + value varchar(255) +); +insert into t1 select seq, seq from seq_1_to_100; + +-- echo # Note: the function is intentionally NOT declared as DETERMINISTIC +delimiter //; +CREATE FUNCTION f1(LOOKUPID_IN INT) RETURNS varchar(255) CHARSET utf8 +BEGIN + DECLARE LOOKUP_VALUE VARCHAR(255); + SET LOOKUP_VALUE = (SELECT value FROM t1 WHERE lookupId = LOOKUPID_IN); + set @counter=@counter+1; + RETURN LOOKUP_VALUE; +END; +// +delimiter ;// + +create table t2 ( + col1 int, + col2 int +); +insert into t2 select mod(seq,100), seq from seq_1_to_1000; + +explain +select f1(col1) from t2 order by col2 desc limit 5; +set @counter=0; +select f1(col1) from t2 order by col2 desc limit 5; +--echo # Must show 5, not 1000: +select @counter; +drop function f1; +drop table t1,t2; diff --git a/mysql-test/main/user_var.result b/mysql-test/main/user_var.result index 924c252b951..a5837996c19 100644 --- a/mysql-test/main/user_var.result +++ b/mysql-test/main/user_var.result @@ -372,14 +372,14 @@ insert into t1 (b) values (10), (30), (10), (10); set @var := 0; explain select if(b=@var, 999, b) , @var := b from t1 order by b; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using temporary; Using filesort +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using filesort set @var := 0; select if(b=@var, 999, b) , @var := b from t1 order by b; if(b=@var, 999, b) @var := b 10 10 -10 10 30 30 999 10 +999 10 drop table t1; create temporary table t1 (id int); insert into t1 values (2), (3), (3), (4); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index dfca2500d6d..5de9782fd09 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -7738,6 +7738,8 @@ bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array, thd->lex->current_select->select_list_tables|= item->used_tables(); thd->lex->used_tables|= item->used_tables(); thd->lex->current_select->cur_pos_in_select_list++; + + thd->lex->current_select->rownum_in_field_list |= item->with_rownum_func(); } thd->lex->current_select->is_item_list_lookup= save_is_item_list_lookup; thd->lex->current_select->cur_pos_in_select_list= UNDEF_POS; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 520982f93b6..b743141598f 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -3002,6 +3002,8 @@ void st_select_lex::init_query() prep_leaf_list_state= UNINIT; bzero((char*) expr_cache_may_be_used, sizeof(expr_cache_may_be_used)); select_list_tables= 0; + rownum_in_field_list= 0; + window_specs.empty(); window_funcs.empty(); tvc= 0; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index e4fe1465c57..82453ad8259 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1344,6 +1344,9 @@ public: */ table_map select_list_tables; + /* Set to 1 if any field in field list has ROWNUM() */ + bool rownum_in_field_list; + /* namp of nesting SELECT visibility (for aggregate functions check) */ nesting_map name_visibility_map; table_map with_dep; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 60b2641e670..446f6e83b0d 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -434,7 +434,6 @@ void JOIN::init(THD *thd_arg, List &fields_arg, no_order= 0; simple_order= 0; simple_group= 0; - rand_table_in_field_list= 0; ordered_index_usage= ordered_index_void; need_distinct= 0; skip_sort_order= 0; @@ -1434,7 +1433,6 @@ JOIN::prepare(TABLE_LIST *tables_init, COND *conds_init, uint og_num, &all_fields, &select_lex->pre_fix, 1)) DBUG_RETURN(-1); thd->lex->current_select->context_analysis_place= save_place; - rand_table_in_field_list= select_lex->select_list_tables & RAND_TABLE_BIT; if (setup_without_group(thd, ref_ptrs, tables_list, select_lex->leaf_tables, fields_list, @@ -14807,7 +14805,7 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond, and some wrong results so better to leave the code as it was related to ROLLUP. */ - *simple_order= !join->rand_table_in_field_list; + *simple_order= !join->select_lex->rownum_in_field_list; if (join->only_const_tables()) return change_list ? 0 : first_order; // No need to sort diff --git a/sql/sql_select.h b/sql/sql_select.h index c9e0fa25421..3332bc78b6c 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -1420,11 +1420,6 @@ public: GROUP/ORDER BY. */ bool simple_order, simple_group; - /* - Set to 1 if any field in field list has RAND_TABLE set. For example if - if one uses RAND() or ROWNUM() in field list - */ - bool rand_table_in_field_list; /* ordered_index_usage is set if an ordered index access