Commit d546d1cc authored by Monty's avatar Monty

Fixed MDEV-8408

Assertion `inited==INDEX' failed in int handler::ha_index_first(uchar*)

The crash was because errors from init_read_record_idx() was not taken care of.
parent df8832ca
START TRANSACTION WITH CONSISTENT SNAPSHOT;
CREATE TABLE IF NOT EXISTS t1 (pk INT PRIMARY KEY, i INT, KEY(i)) ENGINE=InnoDB;
UPDATE t1 SET i = 0;
ERROR HY000: Table definition has changed, please retry transaction
UPDATE t1 SET pk = 0;
ERROR HY000: Table definition has changed, please retry transaction
commit;
drop table t1;
--source include/have_log_bin.inc
--source include/have_binlog_format_row.inc
--source include/have_innodb.inc
START TRANSACTION WITH CONSISTENT SNAPSHOT;
--connect (con1,localhost,root,,test)
CREATE TABLE IF NOT EXISTS t1 (pk INT PRIMARY KEY, i INT, KEY(i)) ENGINE=InnoDB;
--connection default
--error 1412
UPDATE t1 SET i = 0;
--error 1412
UPDATE t1 SET pk = 0;
commit;
drop table t1;
......@@ -66,10 +66,12 @@ static int rr_index_desc(READ_RECORD *info);
@param reverse Scan in the reverse direction
*/
void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table,
bool init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table,
bool print_error, uint idx, bool reverse)
{
int error;
DBUG_ENTER("init_read_record_idx");
empty_record(table);
bzero((char*) info,sizeof(*info));
info->thd= thd;
......@@ -88,6 +90,7 @@ void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table,
/* read_record will be changed to rr_index in rr_index_first */
info->read_record= reverse ? rr_index_last : rr_index_first;
DBUG_RETURN(error != 0);
}
......
......@@ -76,7 +76,7 @@ struct READ_RECORD
bool init_read_record(READ_RECORD *info, THD *thd, TABLE *reg_form,
SQL_SELECT *select, int use_record_cache,
bool print_errors, bool disable_rr_cache);
void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table,
bool init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table,
bool print_error, uint idx, bool reverse);
void end_read_record(READ_RECORD *info);
......
......@@ -508,17 +508,18 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
free_underlaid_joins(thd, select_lex);
DBUG_RETURN(TRUE);
}
if (query_plan.index == MAX_KEY || (select && select->quick))
error= init_read_record(&info, thd, table, select, 1, 1, FALSE);
else
error= init_read_record_idx(&info, thd, table, 1, query_plan.index,
reverse);
if (error)
{
if (init_read_record(&info, thd, table, select, 1, 1, FALSE))
{
delete select;
free_underlaid_joins(thd, select_lex);
DBUG_RETURN(TRUE);
}
delete select;
free_underlaid_joins(thd, select_lex);
DBUG_RETURN(TRUE);
}
else
init_read_record_idx(&info, thd, table, 1, query_plan.index, reverse);
init_ftfuncs(thd, select_lex, 1);
THD_STAGE_INFO(thd, stage_updating);
......
......@@ -459,7 +459,8 @@ int mysql_update(THD *thd,
query_plan.scanned_rows= select? select->records: table->file->stats.records;
if (select && select->quick && select->quick->unique_key_range())
{ // Single row select (always "ordered"): Ok to use with key field UPDATE
{
/* Single row select (always "ordered"): Ok to use with key field UPDATE */
need_sort= FALSE;
query_plan.index= MAX_KEY;
used_key_is_modified= FALSE;
......@@ -468,7 +469,8 @@ int mysql_update(THD *thd,
{
ha_rows scanned_limit= query_plan.scanned_rows;
query_plan.index= get_index_for_order(order, table, select, limit,
&scanned_limit, &need_sort, &reverse);
&scanned_limit, &need_sort,
&reverse);
if (!need_sort)
query_plan.scanned_rows= scanned_limit;
......@@ -481,12 +483,15 @@ int mysql_update(THD *thd,
else
{
if (need_sort)
{ // Assign table scan index to check below for modified key fields:
{
/* Assign table scan index to check below for modified key fields: */
query_plan.index= table->file->key_used_on_scan;
}
if (query_plan.index != MAX_KEY)
{ // Check if we are modifying a key that we are used to search with:
used_key_is_modified= is_key_used(table, query_plan.index, table->write_set);
{
/* Check if we are modifying a key that we are used to search with: */
used_key_is_modified= is_key_used(table, query_plan.index,
table->write_set);
}
}
}
......@@ -597,19 +602,20 @@ int mysql_update(THD *thd,
B. query_plan.index != MAX_KEY
B.1 quick select is used, start the scan with init_read_record
B.2 quick select is not used, this is full index scan (with LIMIT)
Full index scan must be started with init_read_record_idx
Full index scan must be started with init_read_record_idx
*/
if (query_plan.index == MAX_KEY || (select && select->quick))
error= init_read_record(&info, thd, table, select, 0, 1, FALSE);
else
error= init_read_record_idx(&info, thd, table, 1, query_plan.index,
reverse);
if (error)
{
if (init_read_record(&info, thd, table, select, 0, 1, FALSE))
{
close_cached_file(&tempfile);
goto err;
}
close_cached_file(&tempfile);
goto err;
}
else
init_read_record_idx(&info, thd, table, 1, query_plan.index, reverse);
THD_STAGE_INFO(thd, stage_searching_rows_for_update);
ha_rows tmp_limit= limit;
......
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