summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/key.result25
-rw-r--r--mysql-test/r/type_varchar.result23
-rw-r--r--mysql-test/t/key.test13
-rw-r--r--mysql-test/t/type_varchar.test12
-rw-r--r--sql/field.cc33
-rw-r--r--sql/field.h1
-rw-r--r--sql/sql_table.cc25
7 files changed, 126 insertions, 6 deletions
diff --git a/mysql-test/r/key.result b/mysql-test/r/key.result
index 98e8851bb7e..3ad8571aadd 100644
--- a/mysql-test/r/key.result
+++ b/mysql-test/r/key.result
@@ -329,3 +329,28 @@ ERROR 42S21: Duplicate column name 'c1'
alter table t1 add key (c1,c1,c2);
ERROR 42S21: Duplicate column name 'c1'
drop table t1;
+create table t1 (a varchar(10), b varchar(10), key(a(10),b(10)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) default NULL,
+ `b` varchar(10) default NULL,
+ KEY `a` (`a`,`b`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+alter table t1 modify b varchar(20);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(10) default NULL,
+ `b` varchar(20) default NULL,
+ KEY `a` (`a`,`b`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+alter table t1 modify a varchar(20);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(20) default NULL,
+ `b` varchar(20) default NULL,
+ KEY `a` (`a`,`b`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
diff --git a/mysql-test/r/type_varchar.result b/mysql-test/r/type_varchar.result
index 3bd7fe6b175..fed03cd8d71 100644
--- a/mysql-test/r/type_varchar.result
+++ b/mysql-test/r/type_varchar.result
@@ -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;
diff --git a/mysql-test/t/key.test b/mysql-test/t/key.test
index af3509c8454..9db1523be51 100644
--- a/mysql-test/t/key.test
+++ b/mysql-test/t/key.test
@@ -324,3 +324,16 @@ alter table t1 add key (c1,c2,c1);
--error 1060
alter table t1 add key (c1,c1,c2);
drop table t1;
+
+#
+# If we use a partial field for a key that is actually the length of the
+# field, and we extend the field, we end up with a key that includes the
+# whole new length of the field.
+#
+create table t1 (a varchar(10), b varchar(10), key(a(10),b(10)));
+show create table t1;
+alter table t1 modify b varchar(20);
+show create table t1;
+alter table t1 modify a varchar(20);
+show create table t1;
+drop table t1;
diff --git a/mysql-test/t/type_varchar.test b/mysql-test/t/type_varchar.test
index 2bffca6b889..1a3a93018a4 100644
--- a/mysql-test/t/type_varchar.test
+++ b/mysql-test/t/type_varchar.test
@@ -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;
diff --git a/sql/field.cc b/sql/field.cc
index a50190543b5..89ef25475ff 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -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
*/
diff --git a/sql/field.h b/sql/field.h
index d58746b6068..a522558a8d7 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -119,6 +119,7 @@ public:
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)
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 2cf9386d0e4..8a29c481dc1 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -3398,12 +3398,25 @@ 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))
- key_part_length=0; // Use whole field
+ {
+ /*
+ 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.
+
+ We also unset the key part length if it is the same as the
+ old field's length, so the whole new field will be used.
+
+ 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->field->field_length == key_part_length ||
+ (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_parts.push_back(new key_part_spec(cfield->field_name,