Skip to content

Commit 76d257e

Browse files
MDEV-36034 KILL or timeout inside derived table optimization causes an assert
If the call to mysql_handle_single_derived(..., DT_OPTIMIZE) in JOIN::optimize_inner() returns 1, then JOIN::optimize_inner() will also return 1 but will not set JOIN::error. Sql_cmd_dml::execute_inner() would note this error but will return 0 (JOIN::error) to its caller, Sql_cmd_update|delete::execute_inner. The caller will try to print the query plan and hit an assertion due to query plan not being present. Queries affected by the this bug involve explain format=json with a DML statement containing a derived table and some manner of execution abortion, a timeout or kill. Fixed by setting JOIN::error. Approved by: Sergei Petrunia (sergey@mariadb.com)
1 parent 29d8f65 commit 76d257e

File tree

3 files changed

+60
-0
lines changed

3 files changed

+60
-0
lines changed

mysql-test/main/kill.result

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,3 +185,22 @@ DROP TABLE t1, t2;
185185
#
186186
kill query id user 'foo';
187187
ERROR 42S22: Unknown column 'user' in 'KILL'
188+
#
189+
# MDEV-36034 KILL or timeout inside derived table optimization causes an assert
190+
#
191+
CREATE TABLE t10(c int primary key, c2 int) engine=innodb;
192+
CREATE TABLE t20(c INT) engine=innodb;
193+
connect con1, localhost, root;
194+
connection default;
195+
set debug_sync='before_get_quick_record_count SIGNAL target_ready WAIT_FOR target_continue';
196+
explain format=json
197+
update t20,(SELECT * FROM t10)t (a, c)
198+
set t20.c=t.c+10 where t20.c = t.c and t.a >= 3;
199+
connection con1;
200+
set debug_sync='now WAIT_FOR target_ready';
201+
kill query $id;
202+
connection default;
203+
ERROR 70100: Query execution was interrupted
204+
disconnect con1;
205+
drop table t10, t20;
206+
set debug_sync='reset';

mysql-test/main/kill.test

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99

1010
-- source include/count_sessions.inc
1111
-- source include/not_embedded.inc
12+
-- source include/have_innodb.inc
13+
-- source include/have_debug_sync.inc
1214

1315
--disable_service_connection
1416

@@ -320,3 +322,36 @@ DROP TABLE t1, t2;
320322
--error ER_BAD_FIELD_ERROR
321323
kill query id user 'foo';
322324
--enable_service_connection
325+
326+
327+
--echo #
328+
--echo # MDEV-36034 KILL or timeout inside derived table optimization causes an assert
329+
--echo #
330+
331+
CREATE TABLE t10(c int primary key, c2 int) engine=innodb;
332+
CREATE TABLE t20(c INT) engine=innodb;
333+
334+
connect con1, localhost, root;
335+
connection default;
336+
337+
set debug_sync='before_get_quick_record_count SIGNAL target_ready WAIT_FOR target_continue';
338+
let $id=`select connection_id()`;
339+
340+
send
341+
explain format=json
342+
update t20,(SELECT * FROM t10)t (a, c)
343+
set t20.c=t.c+10 where t20.c = t.c and t.a >= 3;
344+
345+
connection con1;
346+
set debug_sync='now WAIT_FOR target_ready';
347+
evalp kill query $id;
348+
349+
connection default;
350+
--error ER_QUERY_INTERRUPTED
351+
reap;
352+
353+
disconnect con1;
354+
355+
drop table t10, t20;
356+
357+
set debug_sync='reset';

sql/sql_select.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2542,7 +2542,10 @@ JOIN::optimize_inner()
25422542
DBUG_RETURN(1);
25432543
}
25442544
if (mysql_handle_single_derived(thd->lex, tbl, DT_OPTIMIZE))
2545+
{
2546+
error= 1;
25452547
DBUG_RETURN(1);
2548+
}
25462549
}
25472550
}
25482551
}
@@ -5436,6 +5439,9 @@ static bool get_quick_record_count(THD *thd, SQL_SELECT *select,
54365439
uchar buff[STACK_BUFF_ALLOC];
54375440
if (unlikely(check_stack_overrun(thd, STACK_MIN_SIZE, buff)))
54385441
DBUG_RETURN(false); // Fatal error flag is set
5442+
5443+
DEBUG_SYNC(thd, "before_get_quick_record_count");
5444+
54395445
if (select)
54405446
{
54415447
select->head=table;

0 commit comments

Comments
 (0)