diff --git a/mysql-test/suite/innodb/r/extend_varchar_column_compressed_bugfix.result b/mysql-test/suite/innodb/r/extend_varchar_column_compressed_bugfix.result new file mode 100644 index 000000000000..a3c571c27ad5 --- /dev/null +++ b/mysql-test/suite/innodb/r/extend_varchar_column_compressed_bugfix.result @@ -0,0 +1,79 @@ +create database database20250708; +# basic bugfix +# -------------------------------------------------------------------- +create table database20250708.t11(c1 varchar(253) column_format compressed)CHARACTER SET ascii; +insert into database20250708.t11 values('qGjZtLxVfDaKbYOpEUmNRWSiHgBcFpLaQwMrSnTzXyCvJuKdFEaBnCdRgTpMwQfJxHyUvIeOzGkSfNbPkYwVcXzAjLmDtFuQiOWdVjAyKfLpUsXnRzBmQeCiTgHoFvYwZxMkNjGbRaEpCuIdSqTFeYgIuBvNxRzQpSmTkCjHzWdVbYaMlEkFhOjZqUcXiDfPgLaRLpZkYjIxGfEdRcBnAmSqUoWtVhNjKpLmFgCvXzQaByTfEuIzR'); +# test from 253 to 254 +alter table database20250708.t11 modify c1 varchar(254) column_format compressed; +select * from database20250708.t11; +c1 +qGjZtLxVfDaKbYOpEUmNRWSiHgBcFpLaQwMrSnTzXyCvJuKdFEaBnCdRgTpMwQfJxHyUvIeOzGkSfNbPkYwVcXzAjLmDtFuQiOWdVjAyKfLpUsXnRzBmQeCiTgHoFvYwZxMkNjGbRaEpCuIdSqTFeYgIuBvNxRzQpSmTkCjHzWdVbYaMlEkFhOjZqUcXiDfPgLaRLpZkYjIxGfEdRcBnAmSqUoWtVhNjKpLmFgCvXzQaByTfEuIzR +SHOW CREATE TABLE database20250708.t11; +Table Create Table +t11 CREATE TABLE `t11` ( + `c1` varchar(254) /*!50633 COLUMN_FORMAT COMPRESSED */ DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=ascii +CHECK TABLE database20250708.t11; +Table Op Msg_type Msg_text +database20250708.t11 check status OK +alter table database20250708.t11 modify c1 varchar(250) column_format compressed; +# test from 250 to 255 +alter table database20250708.t11 modify c1 varchar(255) column_format compressed; +select * from database20250708.t11; +c1 +qGjZtLxVfDaKbYOpEUmNRWSiHgBcFpLaQwMrSnTzXyCvJuKdFEaBnCdRgTpMwQfJxHyUvIeOzGkSfNbPkYwVcXzAjLmDtFuQiOWdVjAyKfLpUsXnRzBmQeCiTgHoFvYwZxMkNjGbRaEpCuIdSqTFeYgIuBvNxRzQpSmTkCjHzWdVbYaMlEkFhOjZqUcXiDfPgLaRLpZkYjIxGfEdRcBnAmSqUoWtVhNjKpLmFgCvXzQaByTfEuIzR +SHOW CREATE TABLE database20250708.t11; +Table Create Table +t11 CREATE TABLE `t11` ( + `c1` varchar(255) /*!50633 COLUMN_FORMAT COMPRESSED */ DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=ascii +CHECK TABLE database20250708.t11; +Table Op Msg_type Msg_text +database20250708.t11 check status OK +# test new threshold 254 in inplace algorithm +alter table database20250708.t11 modify c1 varchar(256) column_format compressed,algorithm=inplace; +SHOW CREATE TABLE database20250708.t11; +Table Create Table +t11 CREATE TABLE `t11` ( + `c1` varchar(256) /*!50633 COLUMN_FORMAT COMPRESSED */ DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=ascii +CHECK TABLE database20250708.t11; +Table Op Msg_type Msg_text +database20250708.t11 check status OK +alter table database20250708.t11 modify c1 varchar(253) column_format compressed; +alter table database20250708.t11 modify c1 varchar(254) column_format compressed,algorithm=inplace; +ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY. +alter table database20250708.t11 modify c1 varchar(252) column_format compressed; +alter table database20250708.t11 modify c1 varchar(256) column_format compressed,algorithm=inplace; +ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY. +# -------------------------------------------------------------------- +# test row log +# -------------------------------------------------------------------- +alter table database20250708.t11 modify c1 varchar(251) column_format compressed; +SET DEBUG_SYNC='alter_table_inplace_after_lock_downgrade SIGNAL update_now WAIT_FOR update_done'; +alter table database20250708.t11 modify c1 varchar(253) column_format compressed,algorithm=inplace; +SET DEBUG_SYNC='now WAIT_FOR update_now'; +insert into database20250708.t11 values('qGjZtLxVfDaKbYOpEUmNRWSiHgBcFpLaQwMrSnTzXyCvJuKdFEaBnCdRgTpMwQfJxHyUvIeOzGkSfNbPkYwVcXzAjLmDtFuQiOWdVjAyKfLpUsXnRzBmQeCiTgHoFvYwZxMkNjGbRaEpCuIdSqTFeYgIuBvNxRzQpSmTkCjHzWdVbYaMlEkFhOjZqUcXiDfPgLaRLpZkYjIxGfEdRcBnAmSqUoWtVhNjKpLmFgCvXzQaByTfEuIzRa1'); +begin; +insert into database20250708.t11 values('qGjZtLxVfDaKbYOpEUmNRWSiHgBcFpLaQwMrSnTzXyCvJuKdFEaBnCdRgTpMwQfJxHyUvIeOzGkSfNbPkYwVcXzAjLmDtFuQiOWdVjAyKfLpUsXnRzBmQeCiTgHoFvYwZxMkNjGbRaEpCuIdSqTFeYgIuBvNxRzQpSmTkCjHzWdVbYaMlEkFhOjZqUcXiDfPgLaRLpZkYjIxGfEdRcBnAmSqUoWtVhNjKpLmFgCvXzQaByTfEuIzRa2'); +delete from database20250708.t11; +rollback; +begin; +update database20250708.t11 set c1 = 'qGjZtLxVfDaKbYOpEUmNRWSiHgBcFpLaQwMrSnTzXyCvJuKdFEaBnCdRgTpMwQfJxHyUvIeOzGkSfNbPkYwVcXzAjLmDtFuQiOWdVjAyKfLpUsXnRzBmQeCiTgHoFvYwZxMkNjGbRaEpCuIdSqTFeYgIuBvNxRzQpSmTkCjHzWdVbYaMlEkFhOjZqUcXiDfPgLaRLpZkYjIxGfEdRcBnAmSqUoWtVhNjKpLmFgCvXzQaByTfEuIzRgg'; +commit; +SET DEBUG_SYNC='now SIGNAL update_done'; +SELECT * FROM database20250708.t11; +c1 +qGjZtLxVfDaKbYOpEUmNRWSiHgBcFpLaQwMrSnTzXyCvJuKdFEaBnCdRgTpMwQfJxHyUvIeOzGkSfNbPkYwVcXzAjLmDtFuQiOWdVjAyKfLpUsXnRzBmQeCiTgHoFvYwZxMkNjGbRaEpCuIdSqTFeYgIuBvNxRzQpSmTkCjHzWdVbYaMlEkFhOjZqUcXiDfPgLaRLpZkYjIxGfEdRcBnAmSqUoWtVhNjKpLmFgCvXzQaByTfEuIzRgg +qGjZtLxVfDaKbYOpEUmNRWSiHgBcFpLaQwMrSnTzXyCvJuKdFEaBnCdRgTpMwQfJxHyUvIeOzGkSfNbPkYwVcXzAjLmDtFuQiOWdVjAyKfLpUsXnRzBmQeCiTgHoFvYwZxMkNjGbRaEpCuIdSqTFeYgIuBvNxRzQpSmTkCjHzWdVbYaMlEkFhOjZqUcXiDfPgLaRLpZkYjIxGfEdRcBnAmSqUoWtVhNjKpLmFgCvXzQaByTfEuIzRgg +SHOW CREATE TABLE database20250708.t11; +Table Create Table +t11 CREATE TABLE `t11` ( + `c1` varchar(253) /*!50633 COLUMN_FORMAT COMPRESSED */ DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=ascii +CHECK TABLE database20250708.t11; +Table Op Msg_type Msg_text +database20250708.t11 check status OK +# -------------------------------------------------------------------- +# clean up +drop database database20250708; diff --git a/mysql-test/suite/innodb/t/extend_varchar_column_compressed_bugfix.test b/mysql-test/suite/innodb/t/extend_varchar_column_compressed_bugfix.test new file mode 100644 index 000000000000..4f351d8e57a9 --- /dev/null +++ b/mysql-test/suite/innodb/t/extend_varchar_column_compressed_bugfix.test @@ -0,0 +1,82 @@ +# Fix extend varchar bug with column compressed +# +# Author : Han Wei +# Date created : 07/08/2025 + +# Run this test only for debug builds and with debug_sync enabled +--source include/have_debug.inc +--source include/have_debug_sync.inc + +connect (con1,localhost,root,,); +connection default; + +create database database20250708; + +--echo # basic bugfix +--echo # -------------------------------------------------------------------- +create table database20250708.t11(c1 varchar(253) column_format compressed)CHARACTER SET ascii; + +insert into database20250708.t11 values('qGjZtLxVfDaKbYOpEUmNRWSiHgBcFpLaQwMrSnTzXyCvJuKdFEaBnCdRgTpMwQfJxHyUvIeOzGkSfNbPkYwVcXzAjLmDtFuQiOWdVjAyKfLpUsXnRzBmQeCiTgHoFvYwZxMkNjGbRaEpCuIdSqTFeYgIuBvNxRzQpSmTkCjHzWdVbYaMlEkFhOjZqUcXiDfPgLaRLpZkYjIxGfEdRcBnAmSqUoWtVhNjKpLmFgCvXzQaByTfEuIzR'); + +--echo # test from 253 to 254 +alter table database20250708.t11 modify c1 varchar(254) column_format compressed; + +select * from database20250708.t11; +SHOW CREATE TABLE database20250708.t11; +CHECK TABLE database20250708.t11; + +alter table database20250708.t11 modify c1 varchar(250) column_format compressed; +--echo # test from 250 to 255 +alter table database20250708.t11 modify c1 varchar(255) column_format compressed; +select * from database20250708.t11; +SHOW CREATE TABLE database20250708.t11; +CHECK TABLE database20250708.t11; + +--echo # test new threshold 254 in inplace algorithm +alter table database20250708.t11 modify c1 varchar(256) column_format compressed,algorithm=inplace; +SHOW CREATE TABLE database20250708.t11; +CHECK TABLE database20250708.t11; + + +alter table database20250708.t11 modify c1 varchar(253) column_format compressed; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table database20250708.t11 modify c1 varchar(254) column_format compressed,algorithm=inplace; + + +alter table database20250708.t11 modify c1 varchar(252) column_format compressed; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table database20250708.t11 modify c1 varchar(256) column_format compressed,algorithm=inplace; + +--echo # -------------------------------------------------------------------- + + +--echo # test row log +--echo # -------------------------------------------------------------------- +alter table database20250708.t11 modify c1 varchar(251) column_format compressed; + +SET DEBUG_SYNC='alter_table_inplace_after_lock_downgrade SIGNAL update_now WAIT_FOR update_done'; +--send alter table database20250708.t11 modify c1 varchar(253) column_format compressed,algorithm=inplace + + +connection con1; +SET DEBUG_SYNC='now WAIT_FOR update_now'; +insert into database20250708.t11 values('qGjZtLxVfDaKbYOpEUmNRWSiHgBcFpLaQwMrSnTzXyCvJuKdFEaBnCdRgTpMwQfJxHyUvIeOzGkSfNbPkYwVcXzAjLmDtFuQiOWdVjAyKfLpUsXnRzBmQeCiTgHoFvYwZxMkNjGbRaEpCuIdSqTFeYgIuBvNxRzQpSmTkCjHzWdVbYaMlEkFhOjZqUcXiDfPgLaRLpZkYjIxGfEdRcBnAmSqUoWtVhNjKpLmFgCvXzQaByTfEuIzRa1'); +begin; +insert into database20250708.t11 values('qGjZtLxVfDaKbYOpEUmNRWSiHgBcFpLaQwMrSnTzXyCvJuKdFEaBnCdRgTpMwQfJxHyUvIeOzGkSfNbPkYwVcXzAjLmDtFuQiOWdVjAyKfLpUsXnRzBmQeCiTgHoFvYwZxMkNjGbRaEpCuIdSqTFeYgIuBvNxRzQpSmTkCjHzWdVbYaMlEkFhOjZqUcXiDfPgLaRLpZkYjIxGfEdRcBnAmSqUoWtVhNjKpLmFgCvXzQaByTfEuIzRa2'); +delete from database20250708.t11; +rollback; +begin; +update database20250708.t11 set c1 = 'qGjZtLxVfDaKbYOpEUmNRWSiHgBcFpLaQwMrSnTzXyCvJuKdFEaBnCdRgTpMwQfJxHyUvIeOzGkSfNbPkYwVcXzAjLmDtFuQiOWdVjAyKfLpUsXnRzBmQeCiTgHoFvYwZxMkNjGbRaEpCuIdSqTFeYgIuBvNxRzQpSmTkCjHzWdVbYaMlEkFhOjZqUcXiDfPgLaRLpZkYjIxGfEdRcBnAmSqUoWtVhNjKpLmFgCvXzQaByTfEuIzRgg'; +commit; + +SET DEBUG_SYNC='now SIGNAL update_done'; + +connection default; +--reap +SELECT * FROM database20250708.t11; +SHOW CREATE TABLE database20250708.t11; +CHECK TABLE database20250708.t11; + +--echo # -------------------------------------------------------------------- +--echo # clean up +drop database database20250708; diff --git a/sql/field.cc b/sql/field.cc index da960287f499..97e28cbfb524 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -161,6 +161,7 @@ bool length_prevents_inplace(const Field &from, const Create_field &to) { "to.max_display_width_in_bytes():%zu", &from, to.field, to.field ? to.field->row_pack_length() : (uint)-1, to.max_display_width_in_bytes())); + size_t threshold_size = 256; if (to.pack_length() < from.pack_length()) { DBUG_PRINT( @@ -170,7 +171,13 @@ bool length_prevents_inplace(const Field &from, const Create_field &to) { return true; } - if (to.max_display_width_in_bytes() >= 256 && from.row_pack_length() < 256) { + if (to.column_format() == COLUMN_FORMAT_TYPE_COMPRESSED && + from.column_format() == COLUMN_FORMAT_TYPE_COMPRESSED) { + threshold_size -= INNOBASE_ZIP_COLUMN_HEADER_LENGTH; + } + + if (to.max_display_width_in_bytes() >= threshold_size && + from.row_pack_length() < threshold_size) { DBUG_PRINT("inplace", ("row_pack_length increases past the 256 threshold, from %u to " "%zu, -> true for '%s'", @@ -179,6 +186,7 @@ bool length_prevents_inplace(const Field &from, const Create_field &to) { DBUG_PRINT("inplace", ("from:%p, to.field:%p, to.field->row_pack_length():%u", &from, to.field, to.field ? to.field->row_pack_length() : (uint)-1)); + DBUG_PRINT("inplace", ("threshold_size:%zu", threshold_size)); return true; } DBUG_PRINT("inplace", ("-> false")); diff --git a/sql/field.h b/sql/field.h index 0bc976bb6761..cfb78cc36a6c 100644 --- a/sql/field.h +++ b/sql/field.h @@ -117,6 +117,13 @@ struct timeval; */ #define portable_sizeof_char_ptr 8 +/* + In InnoDB, the header length of compressed columns is 2 byte. In the + SQL layer, this value is needed to determine whether the inplace + ddl algorithm can be executed in extending varchar DDL. +*/ +#define INNOBASE_ZIP_COLUMN_HEADER_LENGTH 2 + /* Field class hierarchy