Fix Bug #53592 in plugin code, "crash replacing duplicates into table

after fast alter table added unique key". Look up MySQL index number should
go through index translation table.

rb://347, approved by Marko
This commit is contained in:
Jimmy Yang 2010-05-25 22:31:27 -07:00
commit 0aed1f061e
6 changed files with 150 additions and 44 deletions

View file

@ -6673,7 +6673,7 @@ ha_innobase::create(
(int) form->s->primary_key :
-1);
/* Our function row_get_mysql_key_number_for_index assumes
/* Our function innobase_get_mysql_key_number_for_index assumes
the primary key is always number 0, if it exists */
ut_a(primary_key_no == -1 || primary_key_no == 0);
@ -7389,6 +7389,67 @@ ha_innobase::read_time(
return(ranges + (double) rows / (double) total_rows * time_for_scan);
}
/*********************************************************************//**
Calculates the key number used inside MySQL for an Innobase index. We will
first check the "index translation table" for a match of the index to get
the index number. If there does not exist an "index translation table",
or not able to find the index in the translation table, then we will fall back
to the traditional way of looping through dict_index_t list to find a
match. In this case, we have to take into account if we generated a
default clustered index for the table
@return the key number used inside MySQL */
static
unsigned int
innobase_get_mysql_key_number_for_index(
/*====================================*/
INNOBASE_SHARE* share, /*!< in: share structure for index
translation table. */
const TABLE* table, /*!< in: table in MySQL data
dictionary */
dict_table_t* ib_table,/*!< in: table in Innodb data
dictionary */
const dict_index_t* index) /*!< in: index */
{
const dict_index_t* ind;
unsigned int i;
ut_ad(index);
ut_ad(ib_table);
ut_ad(table);
ut_ad(share);
/* If index translation table exists, we will first check
the index through index translation table for a match. */
if (share->idx_trans_tbl.index_mapping) {
for (i = 0; i < share->idx_trans_tbl.index_count; i++) {
if (share->idx_trans_tbl.index_mapping[i] == index) {
return(i);
}
}
/* Print an error message if we cannot find the index
** in the "index translation table". */
sql_print_error("Cannot find index %s in InnoDB index "
"translation table.", index->name);
}
/* If we do not have an "index translation table", or not able
to find the index in the translation table, we'll directly find
matching index in the dict_index_t list */
for (i = 0; i < table->s->keys; i++) {
ind = dict_table_get_index_on_name(
ib_table, table->key_info[i].name);
if (index == ind) {
return(i);
}
}
sql_print_error("Cannot find matching index number for index %s "
"in InnoDB index list.", index->name);
return(0);
}
/*********************************************************************//**
Returns statistics information of the table to the MySQL interpreter,
in various fields of the handle object. */
@ -7658,8 +7719,8 @@ ha_innobase::info(
err_index = trx_get_error_info(prebuilt->trx);
if (err_index) {
errkey = (unsigned int)
row_get_mysql_key_number_for_index(err_index);
errkey = innobase_get_mysql_key_number_for_index(
share, table, ib_table, err_index);
} else {
errkey = (unsigned int) prebuilt->trx->error_key_num;
}

View file

@ -253,15 +253,6 @@ row_table_got_default_clust_index(
/*==============================*/
const dict_table_t* table); /*!< in: table */
/*********************************************************************//**
Calculates the key number used inside MySQL for an Innobase index. We have
to take into account if we generated a default clustered index for the table
@return the key number used inside MySQL */
UNIV_INTERN
ulint
row_get_mysql_key_number_for_index(
/*===============================*/
const dict_index_t* index); /*!< in: index */
/*********************************************************************//**
Does an update or delete of a row for MySQL.
@return error code or DB_SUCCESS */
UNIV_INTERN

View file

@ -1645,37 +1645,6 @@ row_table_got_default_clust_index(
return(dict_index_get_nth_col(clust_index, 0)->mtype == DATA_SYS);
}
/*********************************************************************//**
Calculates the key number used inside MySQL for an Innobase index. We have
to take into account if we generated a default clustered index for the table
@return the key number used inside MySQL */
UNIV_INTERN
ulint
row_get_mysql_key_number_for_index(
/*===============================*/
const dict_index_t* index) /*!< in: index */
{
const dict_index_t* ind;
ulint i;
ut_a(index);
i = 0;
ind = dict_table_get_first_index(index->table);
while (index != ind) {
ind = dict_table_get_next_index(ind);
i++;
}
if (row_table_got_default_clust_index(index->table)) {
ut_a(i > 0);
i--;
}
return(i);
}
/*********************************************************************//**
Locks the data dictionary in shared mode from modifications, for performing
foreign key check, rollback, or other operation invisible to MySQL. */

View file

@ -21,7 +21,7 @@
set -eu
TARGETDIR=../storage/innobase
TARGETDIR=../storage/innodb_plugin
# link the build scripts
BUILDSCRIPTS="compile-innodb compile-innodb-debug"