Commit f0329bfb authored by unknown's avatar unknown

Fix partial keys when converting VARCHAR to TEXT. (Bug #10543)


mysql-test/r/type_varchar.result:
  Update results
mysql-test/t/type_varchar.test:
  Add new regression test
sql/field.cc:
  Add Field::type_can_have_key_part() static method
sql/field.h:
  Add Field::type_can_have_key_part() signature.
sql/sql_table.cc:
  Only reset the length of a key part when changing from a
  field type that can't be used partially to a field that can,
  or vice versa, or when the part is smaller than the length
  of the field.
parent f0f9b595
...@@ -392,3 +392,26 @@ group by t1.b, t1.a; ...@@ -392,3 +392,26 @@ group by t1.b, t1.a;
a b min(t1.b) a b min(t1.b)
22 NULL NULL 22 NULL NULL
drop table t1, t2; drop table t1, t2;
create table t1 (f1 varchar(65500));
create index index1 on t1(f1(10));
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`f1` varchar(65500) default NULL,
KEY `index1` (`f1`(10))
) ENGINE=MyISAM DEFAULT CHARSET=latin1
alter table t1 modify f1 varchar(255);
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`f1` varchar(255) default NULL,
KEY `index1` (`f1`(10))
) ENGINE=MyISAM DEFAULT CHARSET=latin1
alter table t1 modify f1 tinytext;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`f1` tinytext,
KEY `index1` (`f1`(10))
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
...@@ -118,3 +118,15 @@ insert into t2 values (22), (22); ...@@ -118,3 +118,15 @@ insert into t2 values (22), (22);
select t1.a, t1.b, min(t1.b) from t1 inner join t2 ON t2.a = t1.a select t1.a, t1.b, min(t1.b) from t1 inner join t2 ON t2.a = t1.a
group by t1.b, t1.a; group by t1.b, t1.a;
drop table t1, t2; drop table t1, t2;
#
# Bug #10543: convert varchar with index to text
#
create table t1 (f1 varchar(65500));
create index index1 on t1(f1(10));
show create table t1;
alter table t1 modify f1 varchar(255);
show create table t1;
alter table t1 modify f1 tinytext;
show create table t1;
drop table t1;
...@@ -982,6 +982,39 @@ Item_result Field::result_merge_type(enum_field_types field_type) ...@@ -982,6 +982,39 @@ Item_result Field::result_merge_type(enum_field_types field_type)
Static help functions Static help functions
*****************************************************************************/ *****************************************************************************/
/*
Check whether a field type can be partially indexed by a key
This is a static method, rather than a virtual function, because we need
to check the type of a non-Field in mysql_alter_table().
SYNOPSIS
type_can_have_key_part()
type field type
RETURN
TRUE Type can have a prefixed key
FALSE Type can not have a prefixed key
*/
bool Field::type_can_have_key_part(enum enum_field_types type)
{
switch (type) {
case MYSQL_TYPE_VARCHAR:
case MYSQL_TYPE_TINY_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_VAR_STRING:
case MYSQL_TYPE_STRING:
return TRUE;
default:
return FALSE;
}
}
/* /*
Numeric fields base class constructor Numeric fields base class constructor
*/ */
......
...@@ -119,6 +119,7 @@ public: ...@@ -119,6 +119,7 @@ public:
virtual Item_result result_type () const=0; virtual Item_result result_type () const=0;
virtual Item_result cmp_type () const { return result_type(); } virtual Item_result cmp_type () const { return result_type(); }
virtual Item_result cast_to_int_type () const { return result_type(); } virtual Item_result cast_to_int_type () const { return result_type(); }
static bool type_can_have_key_part(enum_field_types);
static enum_field_types field_type_merge(enum_field_types, enum_field_types); static enum_field_types field_type_merge(enum_field_types, enum_field_types);
static Item_result result_merge_type(enum_field_types); static Item_result result_merge_type(enum_field_types);
bool eq(Field *field) bool eq(Field *field)
......
...@@ -3334,12 +3334,21 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -3334,12 +3334,21 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
continue; // Field is removed continue; // Field is removed
uint key_part_length=key_part->length; uint key_part_length=key_part->length;
if (cfield->field) // Not new field if (cfield->field) // Not new field
{ // Check if sub key {
if (cfield->field->type() != FIELD_TYPE_BLOB && /*
(cfield->field->pack_length() == key_part_length || If the field can't have only a part used in a key according to its
cfield->length <= key_part_length / new type, or should not be used partially according to its
key_part->field->charset()->mbmaxlen)) previous type, or the field length is less than the key part
key_part_length=0; // Use whole field length, unset the key part length.
BLOBs may have cfield->length == 0, which is why we test it before
checking whether cfield->length < key_part_length (in chars).
*/
if (!Field::type_can_have_key_part(cfield->field->type()) ||
!Field::type_can_have_key_part(cfield->sql_type) ||
(cfield->length && (cfield->length < key_part_length /
key_part->field->charset()->mbmaxlen)))
key_part_length= 0; // Use whole field
} }
key_part_length /= key_part->field->charset()->mbmaxlen; key_part_length /= key_part->field->charset()->mbmaxlen;
key_parts.push_back(new key_part_spec(cfield->field_name, key_parts.push_back(new key_part_spec(cfield->field_name,
......
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