Skip to content

Commit fe89df4

Browse files
committed
MDEV-31162 Crash for query using ROWNUM over multi-table view with ORDER BY
This bug could cause a crash of the server when processing a query with ROWNUM() if it used in its FROM list a reference to a mergeable view defined as SELECT over more than one table that contained ORDER BY clause. When a mergeable view with ORDER BY clause and without LIMIT clause is used in the FROM list of a query that does not have ORDER BY clause the ORDER BY clause of the view is moved to the query. The code that performed this transformation forgot to delete the moved ORDER BY list from the view. If a query contains ROWNUM() and uses a mergeable multi-table view with ORDER BY then according to the current code of TABLE_LIST::init_derived() the view has to be forcibly materialized. As the query and the view shared the same items in its ORDER BY lists they could not be properly resolved either in the query or in the view. This led to a crash of the server. This patch has returned back the original signature of LEX::can_not_use_merged() to comply with 10.4 code of the condition that checks whether a megeable view has to be forcibly materialized. Approved by Oleksandr Byelkin <sanja@mariadb.com>
1 parent 5f3a4be commit fe89df4

File tree

6 files changed

+98
-9
lines changed

6 files changed

+98
-9
lines changed

mysql-test/main/derived_view.result

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4190,4 +4190,52 @@ Warnings:
41904190
Warning 1287 '@@big_tables' is deprecated and will be removed in a future release
41914191
drop view v;
41924192
drop table t1, t2;
4193+
#
4194+
# MDEV-31162: multi-table mergeable view with ORDER BY used
4195+
# in query with rownum() in WHERE
4196+
#
4197+
create table t1 (a INT) engine=MyISAM;
4198+
insert into t1 values (1),(2);
4199+
create table t2 (b INT) engine=MyISAM;
4200+
insert into t2 values (3),(4);
4201+
create view v1 AS select * from t1 join t2 order by b;
4202+
explain select * from v1 where rownum() <= 2;
4203+
id select_type table type possible_keys key key_len ref rows Extra
4204+
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using temporary; Using filesort
4205+
1 SIMPLE t2 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join)
4206+
select * from v1 where rownum() <= 2;
4207+
a b
4208+
1 3
4209+
2 3
4210+
prepare stmt from "select * from v1 where rownum() <= 2";
4211+
execute stmt;
4212+
a b
4213+
1 3
4214+
2 3
4215+
execute stmt;
4216+
a b
4217+
1 3
4218+
2 3
4219+
deallocate prepare stmt;
4220+
create view v2 AS select * from t1 join t2 order by b/a;
4221+
explain select * from v2 where rownum() <= 2;
4222+
id select_type table type possible_keys key key_len ref rows Extra
4223+
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using temporary; Using filesort
4224+
1 SIMPLE t2 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join)
4225+
select * from v2 where rownum() <= 2;
4226+
a b
4227+
2 3
4228+
1 3
4229+
prepare stmt from "select * from v2 where rownum() <= 2";
4230+
execute stmt;
4231+
a b
4232+
2 3
4233+
1 3
4234+
execute stmt;
4235+
a b
4236+
2 3
4237+
1 3
4238+
deallocate prepare stmt;
4239+
drop view v1,v2;
4240+
drop table t1,t2;
41934241
# End of 10.6 tests

mysql-test/main/derived_view.test

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2773,4 +2773,44 @@ set big_tables=default;
27732773
drop view v;
27742774
drop table t1, t2;
27752775

2776+
--echo #
2777+
--echo # MDEV-31162: multi-table mergeable view with ORDER BY used
2778+
--echo # in query with rownum() in WHERE
2779+
--echo #
2780+
2781+
create table t1 (a INT) engine=MyISAM;
2782+
insert into t1 values (1),(2);
2783+
2784+
create table t2 (b INT) engine=MyISAM;
2785+
insert into t2 values (3),(4);
2786+
2787+
create view v1 AS select * from t1 join t2 order by b;
2788+
let $q1=
2789+
select * from v1 where rownum() <= 2;
2790+
2791+
eval explain $q1;
2792+
--sorted_result
2793+
eval $q1;
2794+
2795+
eval prepare stmt from "$q1";
2796+
--sorted_result
2797+
execute stmt;
2798+
--sorted_result
2799+
execute stmt;
2800+
deallocate prepare stmt;
2801+
2802+
create view v2 AS select * from t1 join t2 order by b/a;
2803+
let $q2=
2804+
select * from v2 where rownum() <= 2;
2805+
2806+
eval explain $q2;
2807+
eval $q2;
2808+
eval prepare stmt from "$q2";
2809+
execute stmt;
2810+
execute stmt;
2811+
deallocate prepare stmt;
2812+
2813+
drop view v1,v2;
2814+
drop table t1,t2;
2815+
27762816
--echo # End of 10.6 tests

sql/sql_lex.cc

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4090,7 +4090,7 @@ bool LEX::can_use_merged()
40904090
TRUE - VIEWs with MERGE algorithms can be used
40914091
*/
40924092

4093-
bool LEX::can_not_use_merged(bool no_update_or_delete)
4093+
bool LEX::can_not_use_merged()
40944094
{
40954095
switch (sql_command) {
40964096
case SQLCOM_CREATE_VIEW:
@@ -4103,10 +4103,6 @@ bool LEX::can_not_use_merged(bool no_update_or_delete)
41034103
case SQLCOM_SHOW_FIELDS:
41044104
return TRUE;
41054105

4106-
case SQLCOM_UPDATE_MULTI:
4107-
case SQLCOM_DELETE_MULTI:
4108-
return no_update_or_delete;
4109-
41104106
default:
41114107
return FALSE;
41124108
}

sql/sql_lex.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3659,7 +3659,7 @@ struct LEX: public Query_tables_list
36593659

36603660
bool can_be_merged();
36613661
bool can_use_merged();
3662-
bool can_not_use_merged(bool no_update_or_delete);
3662+
bool can_not_use_merged();
36633663
bool only_view_structure();
36643664
bool need_correct_ident();
36653665
uint8 get_effective_with_check(TABLE_LIST *view);

sql/sql_view.cc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1808,7 +1808,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
18081808
if (view_is_mergeable &&
18091809
(table->select_lex->master_unit() != &old_lex->unit ||
18101810
old_lex->can_use_merged()) &&
1811-
!old_lex->can_not_use_merged(0))
1811+
!old_lex->can_not_use_merged())
18121812
{
18131813
/* lex should contain at least one table */
18141814
DBUG_ASSERT(view_main_select_tables != 0);
@@ -1841,8 +1841,11 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
18411841
*/
18421842
if (!table->select_lex->master_unit()->is_unit_op() &&
18431843
table->select_lex->order_list.elements == 0)
1844+
{
18441845
table->select_lex->order_list.
18451846
push_back(&lex->first_select_lex()->order_list);
1847+
lex->first_select_lex()->order_list.empty();
1848+
}
18461849
else
18471850
{
18481851
if (old_lex->sql_command == SQLCOM_SELECT &&

sql/table.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9551,8 +9551,10 @@ bool TABLE_LIST::init_derived(THD *thd, bool init_view)
95519551
(!first_select->group_list.elements &&
95529552
!first_select->order_list.elements)) &&
95539553
(is_view() ||
9554-
(optimizer_flag(thd, OPTIMIZER_SWITCH_DERIVED_MERGE) &&
9555-
!thd->lex->can_not_use_merged(1))) &&
9554+
optimizer_flag(thd, OPTIMIZER_SWITCH_DERIVED_MERGE)) &&
9555+
!thd->lex->can_not_use_merged() &&
9556+
!((thd->lex->sql_command == SQLCOM_UPDATE_MULTI ||
9557+
thd->lex->sql_command == SQLCOM_DELETE_MULTI) && !is_view()) &&
95569558
!is_recursive_with_table())
95579559
set_merged_derived();
95589560
else

0 commit comments

Comments
 (0)