Commit 178dccaa authored by Sergey Vojtovich's avatar Sergey Vojtovich

Applying InnoDB snapshot, fixes BUG#51378.

Detailed revision comments:

r6789 | jyang | 2010-03-10 11:18:18 +0200 (Wed, 10 Mar 2010) | 10 lines
branches/zip: If a unique index is on a column prefix, such
unique index cannot be upgrade to primary index even if there
is no primary index already defined. Also fix possible corruption
when initialize "ref_length" value in case there is a mismatch
between MySQL and InnoDB primary key. Fix bug #51378: "Init
'ref_length'  to correct value, in case an out of bound MySQL
primary_key".
rb://262 approved by Marko.
parent 434cf189
...@@ -3304,6 +3304,9 @@ ha_innobase::innobase_initialize_autoinc() ...@@ -3304,6 +3304,9 @@ ha_innobase::innobase_initialize_autoinc()
ulint err; ulint err;
update_thd(ha_thd()); update_thd(ha_thd());
ut_a(prebuilt->trx == thd_to_trx(user_thd));
col_name = field->field_name; col_name = field->field_name;
index = innobase_get_index(table->s->next_number_index); index = innobase_get_index(table->s->next_number_index);
...@@ -3494,23 +3497,67 @@ ha_innobase::open( ...@@ -3494,23 +3497,67 @@ ha_innobase::open(
of length ref_length! */ of length ref_length! */
if (!row_table_got_default_clust_index(ib_table)) { if (!row_table_got_default_clust_index(ib_table)) {
if (primary_key >= MAX_KEY) {
sql_print_error("Table %s has a primary key in InnoDB data "
"dictionary, but not in MySQL!", name);
}
prebuilt->clust_index_was_generated = FALSE; prebuilt->clust_index_was_generated = FALSE;
/* MySQL allocates the buffer for ref. key_info->key_length if (UNIV_UNLIKELY(primary_key >= MAX_KEY)) {
includes space for all key columns + one byte for each column sql_print_error("Table %s has a primary key in "
that may be NULL. ref_length must be as exact as possible to "InnoDB data dictionary, but not "
save space, because all row reference buffers are allocated "in MySQL!", name);
based on ref_length. */
/* This mismatch could cause further problems
if not attended, bring this to the user's attention
by printing a warning in addition to log a message
in the errorlog */
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_NO_SUCH_INDEX,
"InnoDB: Table %s has a "
"primary key in InnoDB data "
"dictionary, but not in "
"MySQL!", name);
/* If primary_key >= MAX_KEY, its (primary_key)
value could be out of bound if continue to index
into key_info[] array. Find InnoDB primary index,
and assign its key_length to ref_length.
In addition, since MySQL indexes are sorted starting
with primary index, unique index etc., initialize
ref_length to the first index key length in
case we fail to find InnoDB cluster index.
Please note, this will not resolve the primary
index mismatch problem, other side effects are
possible if users continue to use the table.
However, we allow this table to be opened so
that user can adopt necessary measures for the
mismatch while still being accessible to the table
date. */
ref_length = table->key_info[0].key_length;
/* Find correspoinding cluster index
key length in MySQL's key_info[] array */
for (ulint i = 0; i < table->s->keys; i++) {
dict_index_t* index;
index = innobase_get_index(i);
if (dict_index_is_clust(index)) {
ref_length =
table->key_info[i].key_length;
}
}
} else {
/* MySQL allocates the buffer for ref.
key_info->key_length includes space for all key
columns + one byte for each column that may be
NULL. ref_length must be as exact as possible to
save space, because all row reference buffers are
allocated based on ref_length. */
ref_length = table->key_info[primary_key].key_length; ref_length = table->key_info[primary_key].key_length;
}
} else { } else {
if (primary_key != MAX_KEY) { if (primary_key != MAX_KEY) {
sql_print_error("Table %s has no primary key in InnoDB data " sql_print_error(
"Table %s has no primary key in InnoDB data "
"dictionary, but has one in MySQL! If you " "dictionary, but has one in MySQL! If you "
"created the table with a MySQL version < " "created the table with a MySQL version < "
"3.23.54 and did not define a primary key, " "3.23.54 and did not define a primary key, "
...@@ -3519,6 +3566,17 @@ ha_innobase::open( ...@@ -3519,6 +3566,17 @@ ha_innobase::open(
"key as the primary key. You can fix this " "key as the primary key. You can fix this "
"error by dump + DROP + CREATE + reimport " "error by dump + DROP + CREATE + reimport "
"of the table.", name); "of the table.", name);
/* This mismatch could cause further problems
if not attended, bring this to the user attention
by printing a warning in addition to log a message
in the errorlog */
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_NO_SUCH_INDEX,
"InnoDB: Table %s has no "
"primary key in InnoDB data "
"dictionary, but has one in "
"MySQL!", name);
} }
prebuilt->clust_index_was_generated = TRUE; prebuilt->clust_index_was_generated = TRUE;
...@@ -5402,9 +5460,6 @@ ha_innobase::innobase_get_index( ...@@ -5402,9 +5460,6 @@ ha_innobase::innobase_get_index(
DBUG_ENTER("innobase_get_index"); DBUG_ENTER("innobase_get_index");
ha_statistic_increment(&SSV::ha_read_key_count); ha_statistic_increment(&SSV::ha_read_key_count);
ut_ad(user_thd == ha_thd());
ut_a(prebuilt->trx == thd_to_trx(user_thd));
if (keynr != MAX_KEY && table->s->keys > 0) { if (keynr != MAX_KEY && table->s->keys > 0) {
key = table->key_info + keynr; key = table->key_info + keynr;
......
...@@ -528,10 +528,12 @@ innobase_create_key_def( ...@@ -528,10 +528,12 @@ innobase_create_key_def(
key_info->name, "PRIMARY"); key_info->name, "PRIMARY");
/* If there is a UNIQUE INDEX consisting entirely of NOT NULL /* If there is a UNIQUE INDEX consisting entirely of NOT NULL
columns, MySQL will treat it as a PRIMARY KEY unless the columns and if the index does not contain column prefix(es)
table already has one. */ (only prefix/part of the column is indexed), MySQL will treat the
index as a PRIMARY KEY unless the table already has one. */
if (!new_primary && (key_info->flags & HA_NOSAME) if (!new_primary && (key_info->flags & HA_NOSAME)
&& (!(key_info->flags & HA_KEY_HAS_PART_KEY_SEG))
&& row_table_got_default_clust_index(table)) { && row_table_got_default_clust_index(table)) {
uint key_part = key_info->key_parts; uint key_part = key_info->key_parts;
......
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