Bug#18776592 INNODB: FAILING ASSERTION: PRIMARY_KEY_NO == -1 ||

PRIMARY_KEY_NO == 0 

This bug is a backport of the following revision of 5.6 source tree:
# committer: Gopal Shankar <gopal.shankar@oracle.com>
# branch nick: priKey56
# timestamp: Wed 2013-05-29 11:11:46 +0530
# message:
#   Bug#16368875 INNODB: FAILING ASSERTION:
This commit is contained in:
Gopal Shankar 2014-06-25 09:50:17 +05:30
parent 6cb3ca5996
commit 119984db0c
3 changed files with 69 additions and 36 deletions

View file

@ -3383,7 +3383,6 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
CHARSET_INFO *ft_key_charset=0; // for FULLTEXT
for (uint column_nr=0 ; (column=cols++) ; column_nr++)
{
uint length;
Key_part_spec *dup_column;
it.rewind();
@ -3515,30 +3514,40 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
key_part_info->fieldnr= field;
key_part_info->offset= (uint16) sql_field->offset;
key_part_info->key_type=sql_field->pack_flag;
length= sql_field->key_length;
uint key_part_length= sql_field->key_length;
if (column->length)
{
if (f_is_blob(sql_field->pack_flag))
{
if ((length=column->length) > max_key_length ||
length > file->max_key_part_length())
key_part_length= column->length;
/*
There is a possibility that the given prefix length is less
than the engine max key part length, but still greater
than the BLOB field max size. We handle this case
using the max_field_size variable below.
*/
uint max_field_size= sql_field->key_length * sql_field->charset->mbmaxlen;
if ((max_field_size && key_part_length > max_field_size) ||
key_part_length > max_key_length ||
key_part_length > file->max_key_part_length())
{
length=min(max_key_length, file->max_key_part_length());
// Given prefix length is too large, adjust it.
key_part_length= min(max_key_length, file->max_key_part_length());
if (max_field_size)
key_part_length= min(key_part_length, max_field_size);
if (key->type == Key::MULTIPLE)
{
/* not a critical problem */
char warn_buff[MYSQL_ERRMSG_SIZE];
my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY),
length);
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_TOO_LONG_KEY, warn_buff);
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_TOO_LONG_KEY, ER(ER_TOO_LONG_KEY),
key_part_length);
/* Align key length to multibyte char boundary */
length-= length % sql_field->charset->mbmaxlen;
key_part_length-= key_part_length % sql_field->charset->mbmaxlen;
}
else
{
my_error(ER_TOO_LONG_KEY,MYF(0),length);
my_error(ER_TOO_LONG_KEY, MYF(0), key_part_length);
DBUG_RETURN(TRUE);
}
}
@ -3546,9 +3555,9 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
// Catch invalid use of partial keys
else if (!f_is_geom(sql_field->pack_flag) &&
// is the key partial?
column->length != length &&
column->length != key_part_length &&
// is prefix length bigger than field length?
(column->length > length ||
(column->length > key_part_length ||
// can the field have a partial key?
!Field::type_can_have_key_part (sql_field->sql_type) ||
// a packed field can't be used in a partial key
@ -3557,43 +3566,42 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
((file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS) &&
// and is this a 'unique' key?
(key_info->flags & HA_NOSAME))))
{
{
my_message(ER_WRONG_SUB_KEY, ER(ER_WRONG_SUB_KEY), MYF(0));
DBUG_RETURN(TRUE);
}
else if (!(file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS))
length=column->length;
key_part_length= column->length;
}
else if (length == 0)
else if (key_part_length == 0)
{
my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->field_name.str);
DBUG_RETURN(TRUE);
}
if (length > file->max_key_part_length() && key->type != Key::FULLTEXT)
if (key_part_length > file->max_key_part_length() &&
key->type != Key::FULLTEXT)
{
length= file->max_key_part_length();
key_part_length= file->max_key_part_length();
if (key->type == Key::MULTIPLE)
{
/* not a critical problem */
char warn_buff[MYSQL_ERRMSG_SIZE];
my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY),
length);
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_TOO_LONG_KEY, warn_buff);
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_TOO_LONG_KEY, ER(ER_TOO_LONG_KEY),
key_part_length);
/* Align key length to multibyte char boundary */
length-= length % sql_field->charset->mbmaxlen;
key_part_length-= key_part_length % sql_field->charset->mbmaxlen;
}
else
{
my_error(ER_TOO_LONG_KEY,MYF(0),length);
my_error(ER_TOO_LONG_KEY, MYF(0), key_part_length);
DBUG_RETURN(TRUE);
}
}
key_part_info->length=(uint16) length;
key_part_info->length= (uint16) key_part_length;
/* Use packed keys for long strings on the first column */
if (!((*db_options) & HA_OPTION_NO_PACK_KEYS) &&
!((create_info->table_options & HA_OPTION_NO_PACK_KEYS)) &&
(length >= KEY_DEFAULT_PACK_LENGTH &&
(key_part_length >= KEY_DEFAULT_PACK_LENGTH &&
(sql_field->sql_type == MYSQL_TYPE_STRING ||
sql_field->sql_type == MYSQL_TYPE_VARCHAR ||
sql_field->pack_flag & FIELDFLAG_BLOB)))
@ -3605,10 +3613,10 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
key_info->flags|= HA_PACK_KEY;
}
/* Check if the key segment is partial, set the key flag accordingly */
if (length != sql_field->key_length)
if (key_part_length != sql_field->key_length)
key_info->flags|= HA_KEY_HAS_PART_KEY_SEG;
key_length+=length;
key_length+= key_part_length;
key_part_info++;
/* Create the key name based on the first column (if not given) */

View file

@ -1525,13 +1525,25 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
primary_key=key;
for (i=0 ; i < keyinfo->key_parts ;i++)
{
uint fieldnr= key_part[i].fieldnr;
if (!fieldnr ||
share->field[fieldnr-1]->null_ptr ||
share->field[fieldnr-1]->key_length() !=
key_part[i].length)
DBUG_ASSERT(key_part[i].fieldnr > 0);
// Table field corresponding to the i'th key part.
Field *table_field= share->field[key_part[i].fieldnr - 1];
/*
If the key column is of NOT NULL BLOB type, then it
will definitly have key prefix. And if key part prefix size
is equal to the BLOB column max size, then we can promote
it to primary key.
*/
if (!table_field->real_maybe_null() &&
table_field->type() == MYSQL_TYPE_BLOB &&
table_field->field_length == key_part[i].length)
continue;
if (table_field->real_maybe_null() ||
table_field->key_length() != key_part[i].length)
{
primary_key=MAX_KEY; // Can't be used
primary_key= MAX_KEY; // Can't be used
break;
}
}

View file

@ -2692,6 +2692,19 @@ i_s_innodb_buffer_page_fill(
table_name = mem_heap_strdup(heap,
index->table_name);
DBUG_EXECUTE_IF("mysql_test_print_index_type",
{
char idx_type[3];
ut_snprintf(idx_type,
sizeof(idx_type),
"%d",
index->type);
index_name=mem_heap_strcat(heap,
index_name,
idx_type);
};);
}
mutex_exit(&dict_sys->mutex);