Commit 119984db authored by Gopal Shankar's avatar Gopal Shankar

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:
parent 6cb3ca59
...@@ -3383,7 +3383,6 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, ...@@ -3383,7 +3383,6 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
CHARSET_INFO *ft_key_charset=0; // for FULLTEXT CHARSET_INFO *ft_key_charset=0; // for FULLTEXT
for (uint column_nr=0 ; (column=cols++) ; column_nr++) for (uint column_nr=0 ; (column=cols++) ; column_nr++)
{ {
uint length;
Key_part_spec *dup_column; Key_part_spec *dup_column;
it.rewind(); it.rewind();
...@@ -3515,30 +3514,40 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, ...@@ -3515,30 +3514,40 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
key_part_info->fieldnr= field; key_part_info->fieldnr= field;
key_part_info->offset= (uint16) sql_field->offset; key_part_info->offset= (uint16) sql_field->offset;
key_part_info->key_type=sql_field->pack_flag; 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 (column->length)
{ {
if (f_is_blob(sql_field->pack_flag)) if (f_is_blob(sql_field->pack_flag))
{ {
if ((length=column->length) > max_key_length || key_part_length= column->length;
length > file->max_key_part_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) if (key->type == Key::MULTIPLE)
{ {
/* not a critical problem */ /* not a critical problem */
char warn_buff[MYSQL_ERRMSG_SIZE]; push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY), ER_TOO_LONG_KEY, ER(ER_TOO_LONG_KEY),
length); key_part_length);
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_TOO_LONG_KEY, warn_buff);
/* Align key length to multibyte char boundary */ /* Align key length to multibyte char boundary */
length-= length % sql_field->charset->mbmaxlen; key_part_length-= key_part_length % sql_field->charset->mbmaxlen;
} }
else else
{ {
my_error(ER_TOO_LONG_KEY,MYF(0),length); my_error(ER_TOO_LONG_KEY, MYF(0), key_part_length);
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
} }
...@@ -3546,9 +3555,9 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, ...@@ -3546,9 +3555,9 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
// Catch invalid use of partial keys // Catch invalid use of partial keys
else if (!f_is_geom(sql_field->pack_flag) && else if (!f_is_geom(sql_field->pack_flag) &&
// is the key partial? // is the key partial?
column->length != length && column->length != key_part_length &&
// is prefix length bigger than field length? // is prefix length bigger than field length?
(column->length > length || (column->length > key_part_length ||
// can the field have a partial key? // can the field have a partial key?
!Field::type_can_have_key_part (sql_field->sql_type) || !Field::type_can_have_key_part (sql_field->sql_type) ||
// a packed field can't be used in a partial key // 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, ...@@ -3557,43 +3566,42 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
((file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS) && ((file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS) &&
// and is this a 'unique' key? // and is this a 'unique' key?
(key_info->flags & HA_NOSAME)))) (key_info->flags & HA_NOSAME))))
{ {
my_message(ER_WRONG_SUB_KEY, ER(ER_WRONG_SUB_KEY), MYF(0)); my_message(ER_WRONG_SUB_KEY, ER(ER_WRONG_SUB_KEY), MYF(0));
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
else if (!(file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS)) 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); my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->field_name.str);
DBUG_RETURN(TRUE); 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) if (key->type == Key::MULTIPLE)
{ {
/* not a critical problem */ /* not a critical problem */
char warn_buff[MYSQL_ERRMSG_SIZE]; push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY), ER_TOO_LONG_KEY, ER(ER_TOO_LONG_KEY),
length); key_part_length);
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_TOO_LONG_KEY, warn_buff);
/* Align key length to multibyte char boundary */ /* Align key length to multibyte char boundary */
length-= length % sql_field->charset->mbmaxlen; key_part_length-= key_part_length % sql_field->charset->mbmaxlen;
} }
else else
{ {
my_error(ER_TOO_LONG_KEY,MYF(0),length); my_error(ER_TOO_LONG_KEY, MYF(0), key_part_length);
DBUG_RETURN(TRUE); 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 */ /* Use packed keys for long strings on the first column */
if (!((*db_options) & HA_OPTION_NO_PACK_KEYS) && if (!((*db_options) & HA_OPTION_NO_PACK_KEYS) &&
!((create_info->table_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_STRING ||
sql_field->sql_type == MYSQL_TYPE_VARCHAR || sql_field->sql_type == MYSQL_TYPE_VARCHAR ||
sql_field->pack_flag & FIELDFLAG_BLOB))) sql_field->pack_flag & FIELDFLAG_BLOB)))
...@@ -3605,10 +3613,10 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, ...@@ -3605,10 +3613,10 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
key_info->flags|= HA_PACK_KEY; key_info->flags|= HA_PACK_KEY;
} }
/* Check if the key segment is partial, set the key flag accordingly */ /* 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_info->flags|= HA_KEY_HAS_PART_KEY_SEG;
key_length+=length; key_length+= key_part_length;
key_part_info++; key_part_info++;
/* Create the key name based on the first column (if not given) */ /* Create the key name based on the first column (if not given) */
......
...@@ -1525,13 +1525,25 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, ...@@ -1525,13 +1525,25 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
primary_key=key; primary_key=key;
for (i=0 ; i < keyinfo->key_parts ;i++) for (i=0 ; i < keyinfo->key_parts ;i++)
{ {
uint fieldnr= key_part[i].fieldnr; DBUG_ASSERT(key_part[i].fieldnr > 0);
if (!fieldnr || // Table field corresponding to the i'th key part.
share->field[fieldnr-1]->null_ptr || Field *table_field= share->field[key_part[i].fieldnr - 1];
share->field[fieldnr-1]->key_length() !=
key_part[i].length) /*
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; break;
} }
} }
......
...@@ -2692,6 +2692,19 @@ i_s_innodb_buffer_page_fill( ...@@ -2692,6 +2692,19 @@ i_s_innodb_buffer_page_fill(
table_name = mem_heap_strdup(heap, table_name = mem_heap_strdup(heap,
index->table_name); 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); mutex_exit(&dict_sys->mutex);
......
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