Commit f0329bfb authored by unknown's avatar unknown
Browse files

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
Loading
Loading
Loading
Loading
+23 −0
Original line number Diff line number Diff line
@@ -392,3 +392,26 @@ group by t1.b, t1.a;
a	b	min(t1.b)
22	NULL	NULL
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;
+12 −0
Original line number Diff line number Diff line
@@ -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 
  group by t1.b, t1.a;
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;
+33 −0
Original line number Diff line number Diff line
@@ -982,6 +982,39 @@ Item_result Field::result_merge_type(enum_field_types field_type)
  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
*/
+1 −0
Original line number Diff line number Diff line
@@ -119,6 +119,7 @@ class Field
  virtual Item_result result_type () const=0;
  virtual Item_result cmp_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 Item_result result_merge_type(enum_field_types);
  bool eq(Field *field)
+15 −6
Original line number Diff line number Diff line
@@ -3334,11 +3334,20 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
	continue;				// Field is removed
      uint key_part_length=key_part->length;
      if (cfield->field)			// Not new field
      {						// Check if sub key
	if (cfield->field->type() != FIELD_TYPE_BLOB &&
	    (cfield->field->pack_length() == key_part_length ||
	     cfield->length <= key_part_length /
			       key_part->field->charset()->mbmaxlen))
      {
        /*
          If the field can't have only a part used in a key according to its
          new type, or should not be used partially according to its
          previous type, or the field length is less than the key part
          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;