From ad17875c0d39453395f33e8c2a39cc4b2601df2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 13 Feb 2019 15:46:52 +0200 Subject: [PATCH] MDEV-15563: Allow instant VARCHAR extension from <128 bytes For up to 127 bytes length, InnoDB would use 1 byte for length, and that byte would always be less than 128. If the maximum length is longer than 255 bytes, InnoDB would use a variable-length encoding for the length, using 1 byte for lengths up to 127 bytes, and 2 bytes for longer lengths. Thus, 1-byte lengths are always compatible when the maximum size changes from less than 128 bytes to anything longer. Field_varstring::is_equal(): Return IS_EQUAL_PACK_LENGTH also when converting from VARCHAR less than 128 bytes to any longer VARCHAR. --- .../suite/innodb/r/alter_varchar_change.result | 17 +++++++++++++++++ .../suite/innodb/t/alter_varchar_change.test | 12 ++++++++++++ sql/field.cc | 12 ++++++++---- 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/mysql-test/suite/innodb/r/alter_varchar_change.result b/mysql-test/suite/innodb/r/alter_varchar_change.result index 25adde6ffe4..2425c8382e0 100644 --- a/mysql-test/suite/innodb/r/alter_varchar_change.result +++ b/mysql-test/suite/innodb/r/alter_varchar_change.result @@ -412,6 +412,23 @@ ALTER TABLE t1 MODIFY f2 VARCHAR(300); CALL get_table_id("test/t1", @tbl1_id); SELECT @tbl1_id = @tbl_id; @tbl1_id = @tbl_id +1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` varchar(300) DEFAULT NULL, + KEY `idx` (`f2`(40)) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1(f1 INT NOT NULL, +f2 VARCHAR(128), +INDEX idx(f2(40)))ENGINE=InnoDB; +CALL get_table_id("test/t1", @tbl_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(300); +CALL get_table_id("test/t1", @tbl1_id); +SELECT @tbl1_id = @tbl_id; +@tbl1_id = @tbl_id 0 SHOW CREATE TABLE t1; Table Create Table diff --git a/mysql-test/suite/innodb/t/alter_varchar_change.test b/mysql-test/suite/innodb/t/alter_varchar_change.test index 7e0c99487b5..7fc770139ad 100644 --- a/mysql-test/suite/innodb/t/alter_varchar_change.test +++ b/mysql-test/suite/innodb/t/alter_varchar_change.test @@ -306,6 +306,18 @@ SELECT @tbl1_id = @tbl_id; SHOW CREATE TABLE t1; DROP TABLE t1; +CREATE TABLE t1(f1 INT NOT NULL, + f2 VARCHAR(128), + INDEX idx(f2(40)))ENGINE=InnoDB; + +CALL get_table_id("test/t1", @tbl_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(300); +CALL get_table_id("test/t1", @tbl1_id); + +SELECT @tbl1_id = @tbl_id; +SHOW CREATE TABLE t1; +DROP TABLE t1; + CREATE TABLE t1(f1 INT NOT NULL, f2 VARCHAR(100), INDEX idx(f2(40)))ENGINE=InnoDB; diff --git a/sql/field.cc b/sql/field.cc index dd125a06bad..85d8ccb069d 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -7901,17 +7901,21 @@ Field *Field_varstring::new_key_field(MEM_ROOT *root, TABLE *new_table, uint Field_varstring::is_equal(Create_field *new_field) { + if (new_field->length < field_length) + return IS_EQUAL_NO; + if (new_field->type_handler() == type_handler() && new_field->charset == field_charset && !new_field->compression_method() == !compression_method()) { if (new_field->length == field_length) return IS_EQUAL_YES; - if (new_field->length > field_length && - ((new_field->length <= 255 && field_length <= 255) || - (new_field->length > 255 && field_length > 255))) - return IS_EQUAL_PACK_LENGTH; // VARCHAR, longer variable length + if (field_length <= 127 || + new_field->length <= 255 || + field_length > 255) + return IS_EQUAL_PACK_LENGTH; // VARCHAR, longer length } + return IS_EQUAL_NO; }