summaryrefslogtreecommitdiff
path: root/sql/sql_table.cc
diff options
context:
space:
mode:
authorGopal Shankar <gopal.shankar@oracle.com>2014-06-25 09:50:17 +0530
committerGopal Shankar <gopal.shankar@oracle.com>2014-06-25 09:50:17 +0530
commit119984db0c1e406c48fda48680c2d97c0d4cd177 (patch)
tree407ba44bdac859b70b6372b2fc210bbb26e6f426 /sql/sql_table.cc
parent6cb3ca5996ee87600102d3846875e5818ebd6f84 (diff)
downloadmariadb-git-119984db0c1e406c48fda48680c2d97c0d4cd177.tar.gz
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:
Diffstat (limited to 'sql/sql_table.cc')
-rw-r--r--sql/sql_table.cc68
1 files changed, 38 insertions, 30 deletions
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index bfed754a90c..1664f94515a 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -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) */