mirror of
https://github.com/MariaDB/server.git
synced 2025-02-01 03:21:53 +01:00
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.
This commit is contained in:
parent
434cf1894c
commit
178dccaae5
2 changed files with 82 additions and 25 deletions
|
@ -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 @@ retry:
|
|||
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);
|
||||
|
||||
ref_length = table->key_info[primary_key].key_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;
|
||||
}
|
||||
} 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;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue