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.
This commit is contained in:
parent
df8832caae
commit
d546d1cc13
8
mysql-test/suite/innodb/r/snapshot.result
Normal file
8
mysql-test/suite/innodb/r/snapshot.result
Normal file
@ -0,0 +1,8 @@
|
||||
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;
|
18
mysql-test/suite/innodb/t/snapshot.test
Normal file
18
mysql-test/suite/innodb/t/snapshot.test
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
--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 @@ public:
|
||||
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))
|
||||
{
|
||||
if (init_read_record(&info, thd, table, select, 1, 1, FALSE))
|
||||
{
|
||||
delete select;
|
||||
free_underlaid_joins(thd, select_lex);
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
}
|
||||
error= init_read_record(&info, thd, table, select, 1, 1, FALSE);
|
||||
else
|
||||
init_read_record_idx(&info, thd, table, 1, query_plan.index, reverse);
|
||||
error= init_read_record_idx(&info, thd, table, 1, query_plan.index,
|
||||
reverse);
|
||||
if (error)
|
||||
{
|
||||
delete select;
|
||||
free_underlaid_joins(thd, select_lex);
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
|
||||
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))
|
||||
{
|
||||
if (init_read_record(&info, thd, table, select, 0, 1, FALSE))
|
||||
{
|
||||
close_cached_file(&tempfile);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
error= init_read_record(&info, thd, table, select, 0, 1, FALSE);
|
||||
else
|
||||
init_read_record_idx(&info, thd, table, 1, query_plan.index, reverse);
|
||||
error= init_read_record_idx(&info, thd, table, 1, query_plan.index,
|
||||
reverse);
|
||||
|
||||
if (error)
|
||||
{
|
||||
close_cached_file(&tempfile);
|
||||
goto err;
|
||||
}
|
||||
|
||||
THD_STAGE_INFO(thd, stage_searching_rows_for_update);
|
||||
ha_rows tmp_limit= limit;
|
||||
|
Loading…
x
Reference in New Issue
Block a user