Skip to content

Commit 6264451

Browse files
committed
MDEV-8114: server crash on updates with joins still on 10.0.18
Check that leaf table list is really built before storing it.
1 parent 9a3b975 commit 6264451

File tree

5 files changed

+86
-4
lines changed

5 files changed

+86
-4
lines changed

mysql-test/r/update_innodb.result

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
CREATE TABLE `t1` (
2+
`c1` int(11) NOT NULL,
3+
`c2` datetime DEFAULT NULL,
4+
PRIMARY KEY (`c1`)
5+
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
6+
CREATE TABLE `t2` (
7+
`c0` varchar(10) NOT NULL,
8+
`c1` int(11) NOT NULL,
9+
`c2` int(11) NOT NULL,
10+
PRIMARY KEY (`c0`,`c1`),
11+
KEY `c1` (`c1`),
12+
KEY `c2` (`c2`)
13+
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
14+
CREATE TABLE `t3` (
15+
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
16+
`c1` datetime NOT NULL,
17+
`c2` bigint(20) NOT NULL,
18+
`c3` int(4) unsigned NOT NULL,
19+
PRIMARY KEY (`id`),
20+
KEY `c2` (`c2`),
21+
KEY `c3` (`c3`)
22+
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
23+
CREATE TABLE `t4` (
24+
`c1` int(11) NOT NULL,
25+
`c2` bigint(20) DEFAULT NULL,
26+
`c3` int(11) NOT NULL
27+
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
28+
CREATE ALGORITHM=UNDEFINED VIEW `v1` AS select `t4`.`c1` AS `c1`,`t4`.`c2` AS `c2`,`t4`.`c3` AS `c3` from `t4`;
29+
UPDATE t1 a JOIN t2 b ON a.c1 = b.c1 JOIN v1 vw ON b.c2 = vw.c1 JOIN t3 del ON vw.c2 = del.c2 SET a.c2 = ( SELECT max(t.c1) FROM t3 t, v1 i WHERE del.c2 = t.c2 AND vw.c3 = i.c3 AND t.c3 = 4 ) WHERE a.c2 IS NULL OR a.c2 < '2011-05-01';
30+
drop view v1;
31+
drop table t1,t2,t3,t4;

mysql-test/t/update_innodb.test

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
--source include/have_innodb.inc
2+
3+
CREATE TABLE `t1` (
4+
`c1` int(11) NOT NULL,
5+
`c2` datetime DEFAULT NULL,
6+
PRIMARY KEY (`c1`)
7+
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
8+
9+
CREATE TABLE `t2` (
10+
`c0` varchar(10) NOT NULL,
11+
`c1` int(11) NOT NULL,
12+
`c2` int(11) NOT NULL,
13+
PRIMARY KEY (`c0`,`c1`),
14+
KEY `c1` (`c1`),
15+
KEY `c2` (`c2`)
16+
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
17+
18+
CREATE TABLE `t3` (
19+
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
20+
`c1` datetime NOT NULL,
21+
`c2` bigint(20) NOT NULL,
22+
`c3` int(4) unsigned NOT NULL,
23+
PRIMARY KEY (`id`),
24+
KEY `c2` (`c2`),
25+
KEY `c3` (`c3`)
26+
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
27+
28+
CREATE TABLE `t4` (
29+
`c1` int(11) NOT NULL,
30+
`c2` bigint(20) DEFAULT NULL,
31+
`c3` int(11) NOT NULL
32+
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
33+
34+
CREATE ALGORITHM=UNDEFINED VIEW `v1` AS select `t4`.`c1` AS `c1`,`t4`.`c2` AS `c2`,`t4`.`c3` AS `c3` from `t4`;
35+
36+
UPDATE t1 a JOIN t2 b ON a.c1 = b.c1 JOIN v1 vw ON b.c2 = vw.c1 JOIN t3 del ON vw.c2 = del.c2 SET a.c2 = ( SELECT max(t.c1) FROM t3 t, v1 i WHERE del.c2 = t.c2 AND vw.c3 = i.c3 AND t.c3 = 4 ) WHERE a.c2 IS NULL OR a.c2 < '2011-05-01';
37+
38+
drop view v1;
39+
drop table t1,t2,t3,t4;

sql/sql_base.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8291,9 +8291,10 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
82918291
if (select_lex->first_cond_optimization)
82928292
{
82938293
leaves.empty();
8294-
if (!select_lex->is_prep_leaf_list_saved)
8294+
if (select_lex->prep_leaf_list_state != SELECT_LEX::SAVED)
82958295
{
82968296
make_leaves_list(leaves, tables, full_table_list, first_select_table);
8297+
select_lex->prep_leaf_list_state= SELECT_LEX::READY;
82978298
select_lex->leaf_tables_exec.empty();
82988299
}
82998300
else

sql/sql_lex.cc

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1882,7 +1882,7 @@ void st_select_lex::init_query()
18821882
exclude_from_table_unique_test= no_wrap_view_item= FALSE;
18831883
nest_level= 0;
18841884
link_next= 0;
1885-
is_prep_leaf_list_saved= FALSE;
1885+
prep_leaf_list_state= UNINIT;
18861886
bzero((char*) expr_cache_may_be_used, sizeof(expr_cache_may_be_used));
18871887
m_non_agg_field_used= false;
18881888
m_agg_func_used= false;
@@ -4129,12 +4129,22 @@ bool st_select_lex::save_prep_leaf_tables(THD *thd)
41294129
{
41304130
List_iterator_fast<TABLE_LIST> li(leaf_tables);
41314131
TABLE_LIST *table;
4132+
4133+
/*
4134+
Check that the SELECT_LEX was really prepared and so tables are setup.
4135+
4136+
It can be subquery in SET clause of UPDATE which was not prepared yet, so
4137+
its tables are not yet setup and ready for storing.
4138+
*/
4139+
if (prep_leaf_list_state != READY)
4140+
return FALSE;
4141+
41324142
while ((table= li++))
41334143
{
41344144
if (leaf_tables_prep.push_back(table))
41354145
return TRUE;
41364146
}
4137-
is_prep_leaf_list_saved= TRUE;
4147+
prep_leaf_list_state= SAVED;
41384148
for (SELECT_LEX_UNIT *u= first_inner_unit(); u; u= u->next_unit())
41394149
{
41404150
for (SELECT_LEX *sl= u->first_select(); sl; sl= sl->next_select())

sql/sql_lex.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -789,7 +789,8 @@ class st_select_lex: public st_select_lex_node
789789
List<TABLE_LIST> leaf_tables;
790790
List<TABLE_LIST> leaf_tables_exec;
791791
List<TABLE_LIST> leaf_tables_prep;
792-
bool is_prep_leaf_list_saved;
792+
enum leaf_list_state {UNINIT, READY, SAVED};
793+
enum leaf_list_state prep_leaf_list_state;
793794
uint insert_tables;
794795
st_select_lex *merged_into; /* select which this select is merged into */
795796
/* (not 0 only for views/derived tables) */

0 commit comments

Comments
 (0)