Skip to content

Commit d546d1c

Browse files
committed
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.
1 parent df8832c commit d546d1c

File tree

6 files changed

+59
-23
lines changed

6 files changed

+59
-23
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
START TRANSACTION WITH CONSISTENT SNAPSHOT;
2+
CREATE TABLE IF NOT EXISTS t1 (pk INT PRIMARY KEY, i INT, KEY(i)) ENGINE=InnoDB;
3+
UPDATE t1 SET i = 0;
4+
ERROR HY000: Table definition has changed, please retry transaction
5+
UPDATE t1 SET pk = 0;
6+
ERROR HY000: Table definition has changed, please retry transaction
7+
commit;
8+
drop table t1;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
2+
--source include/have_log_bin.inc
3+
--source include/have_binlog_format_row.inc
4+
--source include/have_innodb.inc
5+
6+
START TRANSACTION WITH CONSISTENT SNAPSHOT;
7+
8+
--connect (con1,localhost,root,,test)
9+
CREATE TABLE IF NOT EXISTS t1 (pk INT PRIMARY KEY, i INT, KEY(i)) ENGINE=InnoDB;
10+
11+
--connection default
12+
--error 1412
13+
UPDATE t1 SET i = 0;
14+
--error 1412
15+
UPDATE t1 SET pk = 0;
16+
commit;
17+
18+
drop table t1;

sql/records.cc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,12 @@ static int rr_index_desc(READ_RECORD *info);
6666
@param reverse Scan in the reverse direction
6767
*/
6868

69-
void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table,
69+
bool init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table,
7070
bool print_error, uint idx, bool reverse)
7171
{
7272
int error;
73+
DBUG_ENTER("init_read_record_idx");
74+
7375
empty_record(table);
7476
bzero((char*) info,sizeof(*info));
7577
info->thd= thd;
@@ -88,6 +90,7 @@ void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table,
8890

8991
/* read_record will be changed to rr_index in rr_index_first */
9092
info->read_record= reverse ? rr_index_last : rr_index_first;
93+
DBUG_RETURN(error != 0);
9194
}
9295

9396

sql/records.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ struct READ_RECORD
7676
bool init_read_record(READ_RECORD *info, THD *thd, TABLE *reg_form,
7777
SQL_SELECT *select, int use_record_cache,
7878
bool print_errors, bool disable_rr_cache);
79-
void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table,
79+
bool init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table,
8080
bool print_error, uint idx, bool reverse);
8181
void end_read_record(READ_RECORD *info);
8282

sql/sql_delete.cc

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -508,17 +508,18 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
508508
free_underlaid_joins(thd, select_lex);
509509
DBUG_RETURN(TRUE);
510510
}
511+
511512
if (query_plan.index == MAX_KEY || (select && select->quick))
513+
error= init_read_record(&info, thd, table, select, 1, 1, FALSE);
514+
else
515+
error= init_read_record_idx(&info, thd, table, 1, query_plan.index,
516+
reverse);
517+
if (error)
512518
{
513-
if (init_read_record(&info, thd, table, select, 1, 1, FALSE))
514-
{
515-
delete select;
516-
free_underlaid_joins(thd, select_lex);
517-
DBUG_RETURN(TRUE);
518-
}
519+
delete select;
520+
free_underlaid_joins(thd, select_lex);
521+
DBUG_RETURN(TRUE);
519522
}
520-
else
521-
init_read_record_idx(&info, thd, table, 1, query_plan.index, reverse);
522523

523524
init_ftfuncs(thd, select_lex, 1);
524525
THD_STAGE_INFO(thd, stage_updating);

sql/sql_update.cc

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,8 @@ int mysql_update(THD *thd,
459459
query_plan.scanned_rows= select? select->records: table->file->stats.records;
460460

461461
if (select && select->quick && select->quick->unique_key_range())
462-
{ // Single row select (always "ordered"): Ok to use with key field UPDATE
462+
{
463+
/* Single row select (always "ordered"): Ok to use with key field UPDATE */
463464
need_sort= FALSE;
464465
query_plan.index= MAX_KEY;
465466
used_key_is_modified= FALSE;
@@ -468,7 +469,8 @@ int mysql_update(THD *thd,
468469
{
469470
ha_rows scanned_limit= query_plan.scanned_rows;
470471
query_plan.index= get_index_for_order(order, table, select, limit,
471-
&scanned_limit, &need_sort, &reverse);
472+
&scanned_limit, &need_sort,
473+
&reverse);
472474
if (!need_sort)
473475
query_plan.scanned_rows= scanned_limit;
474476

@@ -481,12 +483,15 @@ int mysql_update(THD *thd,
481483
else
482484
{
483485
if (need_sort)
484-
{ // Assign table scan index to check below for modified key fields:
486+
{
487+
/* Assign table scan index to check below for modified key fields: */
485488
query_plan.index= table->file->key_used_on_scan;
486489
}
487490
if (query_plan.index != MAX_KEY)
488-
{ // Check if we are modifying a key that we are used to search with:
489-
used_key_is_modified= is_key_used(table, query_plan.index, table->write_set);
491+
{
492+
/* Check if we are modifying a key that we are used to search with: */
493+
used_key_is_modified= is_key_used(table, query_plan.index,
494+
table->write_set);
490495
}
491496
}
492497
}
@@ -597,19 +602,20 @@ int mysql_update(THD *thd,
597602
B. query_plan.index != MAX_KEY
598603
B.1 quick select is used, start the scan with init_read_record
599604
B.2 quick select is not used, this is full index scan (with LIMIT)
600-
Full index scan must be started with init_read_record_idx
605+
Full index scan must be started with init_read_record_idx
601606
*/
602607

603608
if (query_plan.index == MAX_KEY || (select && select->quick))
609+
error= init_read_record(&info, thd, table, select, 0, 1, FALSE);
610+
else
611+
error= init_read_record_idx(&info, thd, table, 1, query_plan.index,
612+
reverse);
613+
614+
if (error)
604615
{
605-
if (init_read_record(&info, thd, table, select, 0, 1, FALSE))
606-
{
607-
close_cached_file(&tempfile);
608-
goto err;
609-
}
616+
close_cached_file(&tempfile);
617+
goto err;
610618
}
611-
else
612-
init_read_record_idx(&info, thd, table, 1, query_plan.index, reverse);
613619

614620
THD_STAGE_INFO(thd, stage_searching_rows_for_update);
615621
ha_rows tmp_limit= limit;

0 commit comments

Comments
 (0)