diff --git a/mysql-test/main/column_compression.result b/mysql-test/main/column_compression.result index 5ea981cfdc3..e3bccd5f0de 100644 --- a/mysql-test/main/column_compression.result +++ b/mysql-test/main/column_compression.result @@ -2672,3 +2672,241 @@ SET column_compression_threshold=0; INSERT INTO t1 VALUES('aa'); SET column_compression_threshold=DEFAULT; DROP TABLE t1; +# +# MDEV-31724 Compressed varchar values lost on joins when sorting on columns from joined table(s) +# +CREATE TABLE t1 ( +id int(10) unsigned not null, +txt varchar(5000) COMPRESSED NOT NULL DEFAULT '', +PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_bin; +CREATE TABLE t2 ( +id int(10) unsigned not null, +n1 bigint(20) NOT NULL, +n2 bigint(20) NOT NULL, +n3 bigint(20) NOT NULL, +PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_bin; +INSERT INTO t1 VALUES +(1, 'short string < 100 chars'), +(2, 'long string = 99 chars '), +(3, 'long string = 100 chars !'), +(4, 'long string = 101 chars !'); +INSERT INTO t2 VALUES +(1, 24, 1, 1), +(2, 99, 2, 2), +(3, 100, 3, 3), +(4, 101, 4, 4); +SELECT txt, v.* FROM t1 LEFT JOIN t2 v ON t1.id = v.id; +txt id n1 n2 n3 +short string < 100 chars 1 24 1 1 +long string = 99 chars 2 99 2 2 +long string = 100 chars ! 3 100 3 3 +long string = 101 chars ! 4 101 4 4 +SELECT txt, v.* FROM t1 LEFT JOIN t2 v ON t1.id = v.id ORDER BY v.n1; +txt id n1 n2 n3 +short string < 100 chars 1 24 1 1 +long string = 99 chars 2 99 2 2 +long string = 100 chars ! 3 100 3 3 +long string = 101 chars ! 4 101 4 4 +SELECT txt, v.* FROM t1 JOIN t2 v ON t1.id = v.id; +txt id n1 n2 n3 +short string < 100 chars 1 24 1 1 +long string = 99 chars 2 99 2 2 +long string = 100 chars ! 3 100 3 3 +long string = 101 chars ! 4 101 4 4 +SELECT txt, v.* FROM t1 JOIN t2 v ON t1.id = v.id ORDER BY v.n1; +txt id n1 n2 n3 +short string < 100 chars 1 24 1 1 +long string = 99 chars 2 99 2 2 +long string = 100 chars ! 3 100 3 3 +long string = 101 chars ! 4 101 4 4 +DROP TABLE t1, t2; +CREATE OR REPLACE TABLE t1 ( +id INT NOT NULL PRIMARY KEY, +txt varchar(5000) COMPRESSED NOT NULL DEFAULT '' +) CHARSET=utf8mb3; +INSERT INTO t1 VALUES +(1, REPEAT('a', 10)), +(2, REPEAT('b', 99)), +(3, REPEAT('c', 100)), +(4, REPEAT('d', 121)); +SELECT txt, sysdate(6) FROM t1 ORDER BY 2; +txt sysdate(6) +aaaaaaaaaa +bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc +ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd +DROP TABLE t1; +CREATE FUNCTION f1(imax INT, jmax INT) RETURNS TEXT +BEGIN +DECLARE res TEXT DEFAULT 'x'; +FOR i IN 0..imax +DO +FOR j IN 0..jmax +DO +SET res=CONCAT(res, ' ', i, ' ', j); +END FOR; +END FOR; +RETURN res; +END; +$$ +SET @@column_compression_threshold=32; +# VARCHAR1, 8bit, truncation +CREATE TABLE t1 (a VARCHAR(254) COMPRESSED CHARACTER SET latin1); +INSERT INTO t1 VALUES (f1(6,6)); +SELECT LENGTH(a), LEFT(a,30), RIGHT(a,30) FROM t1; +LENGTH(a) LEFT(a,30) RIGHT(a,30) +197 x 0 0 0 1 0 2 0 3 0 4 0 5 0 6 6 6 0 6 1 6 2 6 3 6 4 6 5 6 6 +FLUSH STATUS; +ALTER IGNORE TABLE t1 MODIFY a VARCHAR(4) COMPRESSED CHARACTER SET latin1; +Warnings: +Warning 1265 Data truncated for column 'a' at row 1 +SHOW STATUS LIKE 'Column%compressions'; +Variable_name Value +Column_compressions 0 +Column_decompressions 1 +SELECT LENGTH(a), a FROM t1; +LENGTH(a) a +4 x 0 +DROP TABLE t1; +CREATE TABLE t1 (a VARCHAR(254) COMPRESSED CHARACTER SET latin1); +INSERT INTO t1 VALUES (REPEAT('a',254)); +SELECT LENGTH(a), LEFT(a,30), RIGHT(a,30) FROM t1; +LENGTH(a) LEFT(a,30) RIGHT(a,30) +254 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +FLUSH STATUS; +ALTER IGNORE TABLE t1 MODIFY a VARCHAR(4) COMPRESSED CHARACTER SET latin1; +Warnings: +Warning 1265 Data truncated for column 'a' at row 1 +SHOW STATUS LIKE 'Column%compressions'; +Variable_name Value +Column_compressions 0 +Column_decompressions 1 +SELECT LENGTH(a), a FROM t1; +LENGTH(a) a +4 aaaa +DROP TABLE t1; +# VARCHAR1, 8bit, no truncation +CREATE TABLE t1 (a VARCHAR(250) COMPRESSED CHARACTER SET latin1); +INSERT INTO t1 VALUES (f1(6,6)); +SELECT LENGTH(a), LEFT(a,30), RIGHT(a,30) FROM t1; +LENGTH(a) LEFT(a,30) RIGHT(a,30) +197 x 0 0 0 1 0 2 0 3 0 4 0 5 0 6 6 6 0 6 1 6 2 6 3 6 4 6 5 6 6 +FLUSH STATUS; +ALTER IGNORE TABLE t1 MODIFY a VARCHAR(254) COMPRESSED CHARACTER SET latin1; +SHOW STATUS LIKE 'Column%compressions'; +Variable_name Value +Column_compressions 0 +Column_decompressions 0 +SELECT LENGTH(a), LEFT(a,30), RIGHT(a,30) FROM t1; +LENGTH(a) LEFT(a,30) RIGHT(a,30) +197 x 0 0 0 1 0 2 0 3 0 4 0 5 0 6 6 6 0 6 1 6 2 6 3 6 4 6 5 6 6 +DROP TABLE t1; +# VARCHAR2, 8bit, truncation +CREATE TABLE t1 (a VARCHAR(32000) COMPRESSED CHARACTER SET latin1); +INSERT INTO t1 VALUES (f1(31,31)); +SELECT LENGTH(a), LEFT(a,30), RIGHT(a,30) FROM t1; +LENGTH(a) LEFT(a,30) RIGHT(a,30) +5505 x 0 0 0 1 0 2 0 3 0 4 0 5 0 6 31 27 31 28 31 29 31 30 31 31 +FLUSH STATUS; +ALTER IGNORE TABLE t1 MODIFY a VARCHAR(256) COMPRESSED CHARACTER SET latin1; +Warnings: +Warning 1265 Data truncated for column 'a' at row 1 +SHOW STATUS LIKE 'Column%compressions'; +Variable_name Value +Column_compressions 1 +Column_decompressions 1 +SELECT LENGTH(a), LEFT(a,30), RIGHT(a,30) FROM t1; +LENGTH(a) LEFT(a,30) RIGHT(a,30) +256 x 0 0 0 1 0 2 0 3 0 4 0 5 0 6 1 17 1 18 1 19 1 20 1 21 1 22 +DROP TABLE t1; +# VARCHAR2, 8bit, no truncation +CREATE TABLE t1 (a VARCHAR(32000) COMPRESSED CHARACTER SET latin1); +INSERT INTO t1 VALUES (f1(31,31)); +SELECT LENGTH(a), LEFT(a,30), RIGHT(a, 30) FROM t1; +LENGTH(a) LEFT(a,30) RIGHT(a, 30) +5505 x 0 0 0 1 0 2 0 3 0 4 0 5 0 6 31 27 31 28 31 29 31 30 31 31 +FLUSH STATUS; +ALTER IGNORE TABLE t1 MODIFY a VARCHAR(32001) COMPRESSED CHARACTER SET latin1; +SHOW STATUS LIKE 'Column%compressions'; +Variable_name Value +Column_compressions 0 +Column_decompressions 0 +SELECT LENGTH(a), LEFT(a,30), RIGHT(a, 30) FROM t1; +LENGTH(a) LEFT(a,30) RIGHT(a, 30) +5505 x 0 0 0 1 0 2 0 3 0 4 0 5 0 6 31 27 31 28 31 29 31 30 31 31 +DROP TABLE t1; +# VARCHAR1, multi-byte, truncation +CREATE TABLE t1 (a VARCHAR(80) COMPRESSED CHARACTER SET utf8mb3); +INSERT INTO t1 VALUES (f1(3,3)); +SELECT LENGTH(a), LEFT(a,30), RIGHT(a,30) FROM t1; +LENGTH(a) LEFT(a,30) RIGHT(a,30) +65 x 0 0 0 1 0 2 0 3 1 0 1 1 1 2 0 2 1 2 2 2 3 3 0 3 1 3 2 3 3 +FLUSH STATUS; +ALTER IGNORE TABLE t1 MODIFY a VARCHAR(1) COMPRESSED CHARACTER SET utf8mb3; +Warnings: +Warning 1265 Data truncated for column 'a' at row 1 +SHOW STATUS LIKE 'Column%compressions'; +Variable_name Value +Column_compressions 0 +Column_decompressions 1 +SELECT LENGTH(a), a FROM t1; +LENGTH(a) a +1 x +DROP TABLE t1; +# VARCHAR1, multi-byte, no truncation +CREATE TABLE t1 (a VARCHAR(80) COMPRESSED CHARACTER SET utf8mb3); +INSERT INTO t1 VALUES (f1(3,3)); +SELECT LENGTH(a), LEFT(a,30), RIGHT(a,30) FROM t1; +LENGTH(a) LEFT(a,30) RIGHT(a,30) +65 x 0 0 0 1 0 2 0 3 1 0 1 1 1 2 0 2 1 2 2 2 3 3 0 3 1 3 2 3 3 +FLUSH STATUS; +ALTER IGNORE TABLE t1 MODIFY a VARCHAR(81) COMPRESSED CHARACTER SET utf8mb3; +SHOW STATUS LIKE 'Column%compressions'; +Variable_name Value +Column_compressions 0 +Column_decompressions 0 +SELECT LENGTH(a), LEFT(a,30), RIGHT(a,30) FROM t1; +LENGTH(a) LEFT(a,30) RIGHT(a,30) +65 x 0 0 0 1 0 2 0 3 1 0 1 1 1 2 0 2 1 2 2 2 3 3 0 3 1 3 2 3 3 +DROP TABLE t1; +# VARCHAR2, multi-byte, truncation +CREATE TABLE t1 (a VARCHAR(10000) COMPRESSED CHARACTER SET utf8mb3); +INSERT INTO t1 VALUES (f1(31,31)); +SELECT LENGTH(a), LEFT(a,30), RIGHT(a,30) FROM t1; +LENGTH(a) LEFT(a,30) RIGHT(a,30) +5505 x 0 0 0 1 0 2 0 3 0 4 0 5 0 6 31 27 31 28 31 29 31 30 31 31 +FLUSH STATUS; +ALTER IGNORE TABLE t1 MODIFY a VARCHAR(256) COMPRESSED CHARACTER SET utf8mb3; +Warnings: +Warning 1265 Data truncated for column 'a' at row 1 +SHOW STATUS LIKE 'Column%compressions'; +Variable_name Value +Column_compressions 1 +Column_decompressions 1 +SELECT LENGTH(a), LEFT(a,30), RIGHT(a,30) FROM t1; +LENGTH(a) LEFT(a,30) RIGHT(a,30) +256 x 0 0 0 1 0 2 0 3 0 4 0 5 0 6 1 17 1 18 1 19 1 20 1 21 1 22 +DROP TABLE t1; +# VARCHAR2, multi-byte, no truncation +CREATE TABLE t1 (a VARCHAR(10000) COMPRESSED CHARACTER SET utf8mb3); +INSERT INTO t1 VALUES (f1(31,31)); +SELECT LENGTH(a), LEFT(a,30), RIGHT(a,30) FROM t1; +LENGTH(a) LEFT(a,30) RIGHT(a,30) +5505 x 0 0 0 1 0 2 0 3 0 4 0 5 0 6 31 27 31 28 31 29 31 30 31 31 +FLUSH STATUS; +ALTER IGNORE TABLE t1 MODIFY a VARCHAR(10001) COMPRESSED CHARACTER SET utf8mb3; +SHOW STATUS LIKE 'Column%compressions'; +Variable_name Value +Column_compressions 0 +Column_decompressions 0 +SELECT LENGTH(a), LEFT(a,30), RIGHT(a,30) FROM t1; +LENGTH(a) LEFT(a,30) RIGHT(a,30) +5505 x 0 0 0 1 0 2 0 3 0 4 0 5 0 6 31 27 31 28 31 29 31 30 31 31 +DROP TABLE t1; +SET @@column_compression_threshold=DEFAULT; +DROP FUNCTION f1; +# +# End of 10.4 tests +# diff --git a/mysql-test/main/column_compression.test b/mysql-test/main/column_compression.test index 1560b23ad3e..29e0218749c 100644 --- a/mysql-test/main/column_compression.test +++ b/mysql-test/main/column_compression.test @@ -266,3 +266,178 @@ SET column_compression_threshold=0; INSERT INTO t1 VALUES('aa'); SET column_compression_threshold=DEFAULT; DROP TABLE t1; + + +--echo # +--echo # MDEV-31724 Compressed varchar values lost on joins when sorting on columns from joined table(s) +--echo # + +CREATE TABLE t1 ( + id int(10) unsigned not null, + txt varchar(5000) COMPRESSED NOT NULL DEFAULT '', + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_bin; + +CREATE TABLE t2 ( + id int(10) unsigned not null, + n1 bigint(20) NOT NULL, + n2 bigint(20) NOT NULL, + n3 bigint(20) NOT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_bin; + +INSERT INTO t1 VALUES +(1, 'short string < 100 chars'), +(2, 'long string = 99 chars '), +(3, 'long string = 100 chars !'), +(4, 'long string = 101 chars !'); + +INSERT INTO t2 VALUES +(1, 24, 1, 1), +(2, 99, 2, 2), +(3, 100, 3, 3), +(4, 101, 4, 4); + +SELECT txt, v.* FROM t1 LEFT JOIN t2 v ON t1.id = v.id; +SELECT txt, v.* FROM t1 LEFT JOIN t2 v ON t1.id = v.id ORDER BY v.n1; +SELECT txt, v.* FROM t1 JOIN t2 v ON t1.id = v.id; +SELECT txt, v.* FROM t1 JOIN t2 v ON t1.id = v.id ORDER BY v.n1; + +DROP TABLE t1, t2; + +CREATE OR REPLACE TABLE t1 ( + id INT NOT NULL PRIMARY KEY, + txt varchar(5000) COMPRESSED NOT NULL DEFAULT '' +) CHARSET=utf8mb3; + +INSERT INTO t1 VALUES +(1, REPEAT('a', 10)), +(2, REPEAT('b', 99)), +(3, REPEAT('c', 100)), +(4, REPEAT('d', 121)); + +--replace_column 2 +--sorted_result +SELECT txt, sysdate(6) FROM t1 ORDER BY 2; +DROP TABLE t1; + + +DELIMITER $$; +CREATE FUNCTION f1(imax INT, jmax INT) RETURNS TEXT +BEGIN + DECLARE res TEXT DEFAULT 'x'; + FOR i IN 0..imax + DO + FOR j IN 0..jmax + DO + SET res=CONCAT(res, ' ', i, ' ', j); + END FOR; + END FOR; + RETURN res; +END; +$$ +DELIMITER ;$$ + + +# Let's override the default threshold (100) to force +# comression for VARCHAR1+MB, for example, for: +# VARCHAR(80) CHARACTER SET utf8mb3 + +SET @@column_compression_threshold=32; + +--echo # VARCHAR1, 8bit, truncation +CREATE TABLE t1 (a VARCHAR(254) COMPRESSED CHARACTER SET latin1); +INSERT INTO t1 VALUES (f1(6,6)); +SELECT LENGTH(a), LEFT(a,30), RIGHT(a,30) FROM t1; +FLUSH STATUS; +ALTER IGNORE TABLE t1 MODIFY a VARCHAR(4) COMPRESSED CHARACTER SET latin1; +SHOW STATUS LIKE 'Column%compressions'; +SELECT LENGTH(a), a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a VARCHAR(254) COMPRESSED CHARACTER SET latin1); +INSERT INTO t1 VALUES (REPEAT('a',254)); +SELECT LENGTH(a), LEFT(a,30), RIGHT(a,30) FROM t1; +FLUSH STATUS; +ALTER IGNORE TABLE t1 MODIFY a VARCHAR(4) COMPRESSED CHARACTER SET latin1; +SHOW STATUS LIKE 'Column%compressions'; +SELECT LENGTH(a), a FROM t1; +DROP TABLE t1; + +--echo # VARCHAR1, 8bit, no truncation +CREATE TABLE t1 (a VARCHAR(250) COMPRESSED CHARACTER SET latin1); +INSERT INTO t1 VALUES (f1(6,6)); +SELECT LENGTH(a), LEFT(a,30), RIGHT(a,30) FROM t1; +FLUSH STATUS; +ALTER IGNORE TABLE t1 MODIFY a VARCHAR(254) COMPRESSED CHARACTER SET latin1; +SHOW STATUS LIKE 'Column%compressions'; +SELECT LENGTH(a), LEFT(a,30), RIGHT(a,30) FROM t1; +DROP TABLE t1; + +--echo # VARCHAR2, 8bit, truncation +CREATE TABLE t1 (a VARCHAR(32000) COMPRESSED CHARACTER SET latin1); +INSERT INTO t1 VALUES (f1(31,31)); +SELECT LENGTH(a), LEFT(a,30), RIGHT(a,30) FROM t1; +FLUSH STATUS; +ALTER IGNORE TABLE t1 MODIFY a VARCHAR(256) COMPRESSED CHARACTER SET latin1; +SHOW STATUS LIKE 'Column%compressions'; +SELECT LENGTH(a), LEFT(a,30), RIGHT(a,30) FROM t1; +DROP TABLE t1; + +--echo # VARCHAR2, 8bit, no truncation +CREATE TABLE t1 (a VARCHAR(32000) COMPRESSED CHARACTER SET latin1); +INSERT INTO t1 VALUES (f1(31,31)); +SELECT LENGTH(a), LEFT(a,30), RIGHT(a, 30) FROM t1; +FLUSH STATUS; +ALTER IGNORE TABLE t1 MODIFY a VARCHAR(32001) COMPRESSED CHARACTER SET latin1; +SHOW STATUS LIKE 'Column%compressions'; +SELECT LENGTH(a), LEFT(a,30), RIGHT(a, 30) FROM t1; +DROP TABLE t1; + +--echo # VARCHAR1, multi-byte, truncation +CREATE TABLE t1 (a VARCHAR(80) COMPRESSED CHARACTER SET utf8mb3); +INSERT INTO t1 VALUES (f1(3,3)); +SELECT LENGTH(a), LEFT(a,30), RIGHT(a,30) FROM t1; +FLUSH STATUS; +ALTER IGNORE TABLE t1 MODIFY a VARCHAR(1) COMPRESSED CHARACTER SET utf8mb3; +SHOW STATUS LIKE 'Column%compressions'; +SELECT LENGTH(a), a FROM t1; +DROP TABLE t1; + +--echo # VARCHAR1, multi-byte, no truncation +CREATE TABLE t1 (a VARCHAR(80) COMPRESSED CHARACTER SET utf8mb3); +INSERT INTO t1 VALUES (f1(3,3)); +SELECT LENGTH(a), LEFT(a,30), RIGHT(a,30) FROM t1; +FLUSH STATUS; +ALTER IGNORE TABLE t1 MODIFY a VARCHAR(81) COMPRESSED CHARACTER SET utf8mb3; +SHOW STATUS LIKE 'Column%compressions'; +SELECT LENGTH(a), LEFT(a,30), RIGHT(a,30) FROM t1; +DROP TABLE t1; + +--echo # VARCHAR2, multi-byte, truncation +CREATE TABLE t1 (a VARCHAR(10000) COMPRESSED CHARACTER SET utf8mb3); +INSERT INTO t1 VALUES (f1(31,31)); +SELECT LENGTH(a), LEFT(a,30), RIGHT(a,30) FROM t1; +FLUSH STATUS; +ALTER IGNORE TABLE t1 MODIFY a VARCHAR(256) COMPRESSED CHARACTER SET utf8mb3; +SHOW STATUS LIKE 'Column%compressions'; +SELECT LENGTH(a), LEFT(a,30), RIGHT(a,30) FROM t1; +DROP TABLE t1; + +--echo # VARCHAR2, multi-byte, no truncation +CREATE TABLE t1 (a VARCHAR(10000) COMPRESSED CHARACTER SET utf8mb3); +INSERT INTO t1 VALUES (f1(31,31)); +SELECT LENGTH(a), LEFT(a,30), RIGHT(a,30) FROM t1; +FLUSH STATUS; +ALTER IGNORE TABLE t1 MODIFY a VARCHAR(10001) COMPRESSED CHARACTER SET utf8mb3; +SHOW STATUS LIKE 'Column%compressions'; +SELECT LENGTH(a), LEFT(a,30), RIGHT(a,30) FROM t1; +DROP TABLE t1; + +SET @@column_compression_threshold=DEFAULT; + +DROP FUNCTION f1; + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/sql/field_conv.cc b/sql/field_conv.cc index 7ec93e032e6..7e60e37a36e 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -532,6 +532,40 @@ static void do_expand_string(Copy_field *copy) } +/* + Copy from a Field_varstring with length_bytes==1 + into another Field_varstring with length_bytes==1 + when the target column is not shorter than the source column. + We don't need to calculate the prefix in this case. It works for + - non-compressed and compressed columns + - single byte and multi-byte character sets +*/ +static void do_varstring1_no_truncation(Copy_field *copy) +{ + uint length= (uint) *(uchar*) copy->from_ptr; + DBUG_ASSERT(length <= copy->to_length - 1); + *(uchar*) copy->to_ptr= (uchar) length; + memcpy(copy->to_ptr+1, copy->from_ptr + 1, length); +} + +/* + Copy from a Field_varstring with length_bytes==2 + into another Field_varstring with length_bytes==2 + when the target column is not shorter than the source column. + We don't need to calculate the prefix in this case. It works for + - non-compressed and compressed columns + - single byte and multi-byte character sets +*/ +static void do_varstring2_no_truncation(Copy_field *copy) +{ + uint length= uint2korr(copy->from_ptr); + DBUG_ASSERT(length <= copy->to_length - HA_KEY_BLOB_LENGTH); + int2store(copy->to_ptr, length); + memcpy(copy->to_ptr + HA_KEY_BLOB_LENGTH, + copy->from_ptr + HA_KEY_BLOB_LENGTH, length); +} + + static void do_varstring1(Copy_field *copy) { uint length= (uint) *(uchar*) copy->from_ptr; @@ -776,6 +810,21 @@ Field::Copy_func *Field_varstring::get_copy_func(const Field *from) const length_bytes != ((const Field_varstring*) from)->length_bytes || !compression_method() != !from->compression_method()) return do_field_string; + + if (field_length >= from->field_length) + return length_bytes == 1 ? do_varstring1_no_truncation : + do_varstring2_no_truncation; + + if (compression_method()) + { + /* + Truncation is going to happen, so we need to calculate prefixes. + Can't calculate prefixes directly on compressed data, + need to go through val_str() to uncompress. + */ + return do_field_string; + } + return length_bytes == 1 ? (from->charset()->mbmaxlen == 1 ? do_varstring1 : do_varstring1_mb) : (from->charset()->mbmaxlen == 1 ? do_varstring2 : do_varstring2_mb);