Skip to content

Commit 8f4de38

Browse files
committed
MDEV-18467 Server crashes in fix_semijoin_strategies_for_picked_join_order
If a splittable materialized derived table / view T is used in a inner nest of an outer join with impossible ON condition then T is marked as a constant table. Yet the execution plan to build T is still searched for in spite of the fact that is not needed. So it should be set.
1 parent a2fc369 commit 8f4de38

File tree

5 files changed

+81
-6
lines changed

5 files changed

+81
-6
lines changed

mysql-test/main/derived_split_innodb.result

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,3 +99,44 @@ id select_type table type possible_keys key key_len ref rows Extra
9999
2 LATERAL DERIVED t1 eq_ref PRIMARY PRIMARY 4 test.t2.id 1
100100
set join_cache_level=default;
101101
DROP TABLE t1,t2;
102+
#
103+
# Bug mdev-18467: join of grouping view and a base table as inner operand
104+
# of left join with on condition containing impossible range
105+
#
106+
create table t1 (f1 int, f2 int, key(f2)) engine=InnoDB;
107+
insert into t1 values (3,33), (7,77), (1,11);
108+
create table t2 (f1 int, f2 int, primary key (f1)) engine=InnoDB;
109+
insert into t2 values (3,33), (9,99), (1,11);
110+
create view v1 as
111+
select f1, max(f2) as f2 from t2 group by f1;
112+
select t.f2
113+
from t1
114+
left join
115+
(v1 join t1 as t on v1.f1=t.f1 and t.f2 = null)
116+
on t1.f1=t.f1;
117+
f2
118+
NULL
119+
NULL
120+
NULL
121+
explain select t.f2
122+
from t1
123+
left join
124+
(v1 join t1 as t on v1.f1=t.f1 and t.f2 = null)
125+
on t1.f1=t.f1;
126+
id select_type table type possible_keys key key_len ref rows Extra
127+
1 PRIMARY t const f2 NULL NULL NULL 1 Impossible ON condition
128+
1 PRIMARY <derived2> const key1 NULL NULL NULL 1 Impossible ON condition
129+
1 PRIMARY t1 ALL NULL NULL NULL NULL 3
130+
2 DERIVED t2 ALL PRIMARY NULL NULL NULL 3 Using temporary; Using filesort
131+
set statement optimizer_switch='split_materialized=off' for explain select t.f2
132+
from t1
133+
left join
134+
(v1 join t1 as t on v1.f1=t.f1 and t.f2 = null)
135+
on t1.f1=t.f1;
136+
id select_type table type possible_keys key key_len ref rows Extra
137+
1 PRIMARY t const f2 NULL NULL NULL 1 Impossible ON condition
138+
1 PRIMARY <derived2> const key1 NULL NULL NULL 1 Impossible ON condition
139+
1 PRIMARY t1 ALL NULL NULL NULL NULL 3
140+
2 DERIVED t2 index NULL PRIMARY 4 NULL 3
141+
drop view v1;
142+
drop table t1,t2;

mysql-test/main/derived_split_innodb.test

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,3 +94,32 @@ eval EXPLAIN $q;
9494
set join_cache_level=default;
9595

9696
DROP TABLE t1,t2;
97+
98+
--echo #
99+
--echo # Bug mdev-18467: join of grouping view and a base table as inner operand
100+
--echo # of left join with on condition containing impossible range
101+
--echo #
102+
103+
create table t1 (f1 int, f2 int, key(f2)) engine=InnoDB;
104+
insert into t1 values (3,33), (7,77), (1,11);
105+
106+
create table t2 (f1 int, f2 int, primary key (f1)) engine=InnoDB;
107+
insert into t2 values (3,33), (9,99), (1,11);
108+
109+
create view v1 as
110+
select f1, max(f2) as f2 from t2 group by f1;
111+
112+
let $q=
113+
select t.f2
114+
from t1
115+
left join
116+
(v1 join t1 as t on v1.f1=t.f1 and t.f2 = null)
117+
on t1.f1=t.f1;
118+
119+
eval $q;
120+
eval explain $q;
121+
eval set statement optimizer_switch='split_materialized=off' for explain $q;
122+
123+
drop view v1;
124+
125+
drop table t1,t2;

sql/opt_split.cc

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1078,6 +1078,7 @@ bool JOIN::inject_best_splitting_cond(table_map remaining_tables)
10781078
@param
10791079
spl_plan info on the splitting plan chosen for the splittable table T
10801080
remaining_tables the table T is joined just before these tables
1081+
is_const_table the table T is a constant table
10811082
10821083
@details
10831084
If in the final query plan the optimizer has chosen a splitting plan
@@ -1091,12 +1092,13 @@ bool JOIN::inject_best_splitting_cond(table_map remaining_tables)
10911092
*/
10921093

10931094
bool JOIN_TAB::fix_splitting(SplM_plan_info *spl_plan,
1094-
table_map remaining_tables)
1095+
table_map remaining_tables,
1096+
bool is_const_table)
10951097
{
10961098
SplM_opt_info *spl_opt_info= table->spl_opt_info;
10971099
DBUG_ASSERT(table->spl_opt_info != 0);
10981100
JOIN *md_join= spl_opt_info->join;
1099-
if (spl_plan)
1101+
if (spl_plan && !is_const_table)
11001102
{
11011103
memcpy((char *) md_join->best_positions,
11021104
(char *) spl_plan->best_positions,
@@ -1113,7 +1115,7 @@ bool JOIN_TAB::fix_splitting(SplM_plan_info *spl_plan,
11131115
remaining_tables,
11141116
true);
11151117
}
1116-
else
1118+
else if (md_join->save_qep)
11171119
{
11181120
md_join->restore_query_plan(md_join->save_qep);
11191121
}
@@ -1143,10 +1145,11 @@ bool JOIN::fix_all_splittings_in_plan()
11431145
{
11441146
POSITION *cur_pos= &best_positions[tablenr];
11451147
JOIN_TAB *tab= cur_pos->table;
1146-
if (tablenr >= const_tables && tab->table->is_splittable())
1148+
if (tab->table->is_splittable())
11471149
{
11481150
SplM_plan_info *spl_plan= cur_pos->spl_plan;
1149-
if (tab->fix_splitting(spl_plan, all_tables & ~prev_tables))
1151+
if (tab->fix_splitting(spl_plan, all_tables & ~prev_tables,
1152+
tablenr < const_tables ))
11501153
return true;
11511154
}
11521155
prev_tables|= tab->table->map;

sql/sql_select.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6689,6 +6689,7 @@ void set_position(JOIN *join,uint idx,JOIN_TAB *table,KEYUSE *key)
66896689
next=tmp;
66906690
}
66916691
join->best_ref[idx]=table;
6692+
join->positions[idx].spl_plan= 0;
66926693
}
66936694

66946695

sql/sql_select.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -659,7 +659,8 @@ typedef struct st_join_table {
659659
void add_keyuses_for_splitting();
660660
SplM_plan_info *choose_best_splitting(double record_count,
661661
table_map remaining_tables);
662-
bool fix_splitting(SplM_plan_info *spl_plan, table_map remaining_tables);
662+
bool fix_splitting(SplM_plan_info *spl_plan, table_map remaining_tables,
663+
bool is_const_table);
663664
} JOIN_TAB;
664665

665666

0 commit comments

Comments
 (0)