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()
ulint err;
update_thd(ha_thd());
ut_a(prebuilt->trx == thd_to_trx(user_thd));
col_name = field->field_name;
index = innobase_get_index(table->s->next_number_index);
......@@ -3494,31 +3497,86 @@ ha_innobase::open(
of length ref_length! */
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;
/* 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. */
if (UNIV_UNLIKELY(primary_key >= MAX_KEY)) {
sql_print_error("Table %s has a primary key in "
"InnoDB data dictionary, but not "
"in MySQL!", name);
/* 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 {
if (primary_key != MAX_KEY) {
sql_print_error("Table %s has no primary key in InnoDB data "
"dictionary, but has one in MySQL! If you "
"created the table with a MySQL version < "
"3.23.54 and did not define a primary key, "
"but defined a unique key with all non-NULL "
"columns, then MySQL internally treats that "
"key as the primary key. You can fix this "
"error by dump + DROP + CREATE + reimport "
"of the table.", name);
sql_print_error(
"Table %s has no primary key in InnoDB data "
"dictionary, but has one in MySQL! If you "
"created the table with a MySQL version < "
"3.23.54 and did not define a primary key, "
"but defined a unique key with all non-NULL "
"columns, then MySQL internally treats that "
"key as the primary key. You can fix this "
"error by dump + DROP + CREATE + reimport "
"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;
......@@ -5402,9 +5460,6 @@ ha_innobase::innobase_get_index(
DBUG_ENTER("innobase_get_index");
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) {
key = table->key_info + keynr;
......
......@@ -528,12 +528,14 @@ innobase_create_key_def(
key_info->name, "PRIMARY");
/* If there is a UNIQUE INDEX consisting entirely of NOT NULL
columns, MySQL will treat it as a PRIMARY KEY unless the
table already has one. */
columns and if the index does not contain column prefix(es)
(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)
&& (!(key_info->flags & HA_KEY_HAS_PART_KEY_SEG))
&& row_table_got_default_clust_index(table)) {
uint key_part = key_info->key_parts;
uint key_part = key_info->key_parts;
new_primary = TRUE;
......
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