Commit ef9e3e73 authored by Sergei Petrunia's avatar Sergei Petrunia

MDEV-30651: Assertion `sel->quick' in make_range_rowid_filters

(Variant for 10.6: return error code from SQL_SELECT::test_quick_select)
The optimizer deals with Rowid Filters this way:

1. First, range optimizer is invoked. It saves information
   about all potential range accesses.
2. A query plan is chosen. Suppose, it uses a Rowid Filter on
   index $IDX.
3. JOIN::make_range_rowid_filters() calls the range optimizer
again to create a quick select on index $IDX which will be used
to populate the rowid filter.

The problem: KILL command catches the query in step #3. Quick
Select is not created which causes a crash.

Fixed by checking if query was killed.
parent e60acae6
...@@ -55,5 +55,33 @@ disconnect con1; ...@@ -55,5 +55,33 @@ disconnect con1;
reap; reap;
set debug_sync='RESET'; set debug_sync='RESET';
--echo #
--echo # MDEV-30651: SIGSEGV in st_join_table::save_explain_data and
--echo # Assertion `sel->quick' failed in make_range_rowid_filters
--echo #
--echo # Reusing table t2 and t3 from previous test
let $target_id= `select connection_id()`;
set debug_sync='in_forced_range_optimize SIGNAL ready1 WAIT_FOR go1';
send
explain
select * from t2, t3
where
t3.key1=t2.a and t3.key2 in (2,3);
connect (con1, localhost, root,,);
set debug_sync='now WAIT_FOR ready1';
evalp kill query $target_id;
set debug_sync='now SIGNAL go1';
connection default;
disconnect con1;
--error ER_QUERY_INTERRUPTED
reap;
set debug_sync='RESET';
drop table t2,t3; drop table t2,t3;
--source include/wait_until_count_sessions.inc --source include/wait_until_count_sessions.inc
...@@ -46,5 +46,23 @@ connection default; ...@@ -46,5 +46,23 @@ connection default;
disconnect con1; disconnect con1;
ERROR 70100: Query execution was interrupted ERROR 70100: Query execution was interrupted
set debug_sync='RESET'; set debug_sync='RESET';
#
# MDEV-30651: SIGSEGV in st_join_table::save_explain_data and
# Assertion `sel->quick' failed in make_range_rowid_filters
#
# Reusing table t2 and t3 from previous test
set debug_sync='in_forced_range_optimize SIGNAL ready1 WAIT_FOR go1';
explain
select * from t2, t3
where
t3.key1=t2.a and t3.key2 in (2,3);
connect con1, localhost, root,,;
set debug_sync='now WAIT_FOR ready1';
kill query $target_id;
set debug_sync='now SIGNAL go1';
connection default;
disconnect con1;
ERROR 70100: Query execution was interrupted
set debug_sync='RESET';
drop table t2,t3; drop table t2,t3;
set default_storage_engine=default; set default_storage_engine=default;
...@@ -45,4 +45,22 @@ connection default; ...@@ -45,4 +45,22 @@ connection default;
disconnect con1; disconnect con1;
ERROR 70100: Query execution was interrupted ERROR 70100: Query execution was interrupted
set debug_sync='RESET'; set debug_sync='RESET';
#
# MDEV-30651: SIGSEGV in st_join_table::save_explain_data and
# Assertion `sel->quick' failed in make_range_rowid_filters
#
# Reusing table t2 and t3 from previous test
set debug_sync='in_forced_range_optimize SIGNAL ready1 WAIT_FOR go1';
explain
select * from t2, t3
where
t3.key1=t2.a and t3.key2 in (2,3);
connect con1, localhost, root,,;
set debug_sync='now WAIT_FOR ready1';
kill query $target_id;
set debug_sync='now SIGNAL go1';
connection default;
disconnect con1;
ERROR 70100: Query execution was interrupted
set debug_sync='RESET';
drop table t2,t3; drop table t2,t3;
...@@ -2720,7 +2720,10 @@ SQL_SELECT::test_quick_select(THD *thd, ...@@ -2720,7 +2720,10 @@ SQL_SELECT::test_quick_select(THD *thd,
only_single_index_range_scan= 1; only_single_index_range_scan= 1;
if (head->force_index || force_quick_range) if (head->force_index || force_quick_range)
{
DEBUG_SYNC(thd, "in_forced_range_optimize");
scan_time= read_time= DBL_MAX; scan_time= read_time= DBL_MAX;
}
else else
{ {
scan_time= rows2double(records) / TIME_FOR_COMPARE; scan_time= rows2double(records) / TIME_FOR_COMPARE;
...@@ -3117,6 +3120,12 @@ SQL_SELECT::test_quick_select(THD *thd, ...@@ -3117,6 +3120,12 @@ SQL_SELECT::test_quick_select(THD *thd,
free_root(&alloc,MYF(0)); // Return memory & allocator free_root(&alloc,MYF(0)); // Return memory & allocator
thd->mem_root= param.old_root; thd->mem_root= param.old_root;
thd->no_errors=0; thd->no_errors=0;
if (thd->killed || thd->is_error())
{
delete quick;
quick= NULL;
returnval= ERROR;
}
} }
DBUG_EXECUTE("info", print_quick(quick, &needed_reg);); DBUG_EXECUTE("info", print_quick(quick, &needed_reg););
......
...@@ -1987,6 +1987,7 @@ bool JOIN::make_range_rowid_filters() ...@@ -1987,6 +1987,7 @@ bool JOIN::make_range_rowid_filters()
tab->table->force_index= force_index_save; tab->table->force_index= force_index_save;
if (rc == SQL_SELECT::ERROR || thd->is_error()) if (rc == SQL_SELECT::ERROR || thd->is_error())
{ {
delete sel;
DBUG_RETURN(true); /* Fatal error */ DBUG_RETURN(true); /* Fatal error */
} }
/* /*
...@@ -2012,8 +2013,6 @@ bool JOIN::make_range_rowid_filters() ...@@ -2012,8 +2013,6 @@ bool JOIN::make_range_rowid_filters()
continue; continue;
} }
no_filter: no_filter:
if (sel->quick)
delete sel->quick;
delete sel; delete sel;
} }
...@@ -2031,7 +2030,9 @@ bool JOIN::make_range_rowid_filters() ...@@ -2031,7 +2030,9 @@ bool JOIN::make_range_rowid_filters()
rowid container employed by the filter. On success it lets the table engine rowid container employed by the filter. On success it lets the table engine
know that what rowid filter will be used when accessing the table rows. know that what rowid filter will be used when accessing the table rows.
@retval false always @retval
false OK
true Error, query should abort
*/ */
bool bool
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment