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); ...@@ -66,10 +66,12 @@ static int rr_index_desc(READ_RECORD *info);
@param reverse Scan in the reverse direction @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) bool print_error, uint idx, bool reverse)
{ {
int error; int error;
DBUG_ENTER("init_read_record_idx");
empty_record(table); empty_record(table);
bzero((char*) info,sizeof(*info)); bzero((char*) info,sizeof(*info));
info->thd= thd; info->thd= thd;
...@@ -88,6 +90,7 @@ void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table, ...@@ -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 */ /* read_record will be changed to rr_index in rr_index_first */
info->read_record= reverse ? rr_index_last : rr_index_first; info->read_record= reverse ? rr_index_last : rr_index_first;
DBUG_RETURN(error != 0);
} }
......
...@@ -76,7 +76,7 @@ public: ...@@ -76,7 +76,7 @@ public:
bool init_read_record(READ_RECORD *info, THD *thd, TABLE *reg_form, bool init_read_record(READ_RECORD *info, THD *thd, TABLE *reg_form,
SQL_SELECT *select, int use_record_cache, SQL_SELECT *select, int use_record_cache,
bool print_errors, bool disable_rr_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); bool print_error, uint idx, bool reverse);
void end_read_record(READ_RECORD *info); void end_read_record(READ_RECORD *info);
......
...@@ -508,17 +508,18 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ...@@ -508,17 +508,18 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
free_underlaid_joins(thd, select_lex); free_underlaid_joins(thd, select_lex);
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
if (query_plan.index == MAX_KEY || (select && select->quick)) if (query_plan.index == MAX_KEY || (select && select->quick))
{ error= init_read_record(&info, thd, table, select, 1, 1, FALSE);
if (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)
{ {
delete select; delete select;
free_underlaid_joins(thd, select_lex); free_underlaid_joins(thd, select_lex);
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
}
else
init_read_record_idx(&info, thd, table, 1, query_plan.index, reverse);
init_ftfuncs(thd, select_lex, 1); init_ftfuncs(thd, select_lex, 1);
THD_STAGE_INFO(thd, stage_updating); THD_STAGE_INFO(thd, stage_updating);
......
...@@ -459,7 +459,8 @@ int mysql_update(THD *thd, ...@@ -459,7 +459,8 @@ int mysql_update(THD *thd,
query_plan.scanned_rows= select? select->records: table->file->stats.records; query_plan.scanned_rows= select? select->records: table->file->stats.records;
if (select && select->quick && select->quick->unique_key_range()) 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; need_sort= FALSE;
query_plan.index= MAX_KEY; query_plan.index= MAX_KEY;
used_key_is_modified= FALSE; used_key_is_modified= FALSE;
...@@ -468,7 +469,8 @@ int mysql_update(THD *thd, ...@@ -468,7 +469,8 @@ int mysql_update(THD *thd,
{ {
ha_rows scanned_limit= query_plan.scanned_rows; ha_rows scanned_limit= query_plan.scanned_rows;
query_plan.index= get_index_for_order(order, table, select, limit, query_plan.index= get_index_for_order(order, table, select, limit,
&scanned_limit, &need_sort, &reverse); &scanned_limit, &need_sort,
&reverse);
if (!need_sort) if (!need_sort)
query_plan.scanned_rows= scanned_limit; query_plan.scanned_rows= scanned_limit;
...@@ -481,12 +483,15 @@ int mysql_update(THD *thd, ...@@ -481,12 +483,15 @@ int mysql_update(THD *thd,
else else
{ {
if (need_sort) 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; query_plan.index= table->file->key_used_on_scan;
} }
if (query_plan.index != MAX_KEY) 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);
} }
} }
} }
...@@ -601,15 +606,16 @@ int mysql_update(THD *thd, ...@@ -601,15 +606,16 @@ int mysql_update(THD *thd,
*/ */
if (query_plan.index == MAX_KEY || (select && select->quick)) if (query_plan.index == MAX_KEY || (select && select->quick))
{ error= init_read_record(&info, thd, table, select, 0, 1, FALSE);
if (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)
{ {
close_cached_file(&tempfile); close_cached_file(&tempfile);
goto err; goto err;
} }
}
else
init_read_record_idx(&info, thd, table, 1, query_plan.index, reverse);
THD_STAGE_INFO(thd, stage_searching_rows_for_update); THD_STAGE_INFO(thd, stage_searching_rows_for_update);
ha_rows tmp_limit= limit; 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