diff options
author | Alexander Barkov <bar@mariadb.com> | 2022-10-25 11:53:39 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.com> | 2022-10-25 17:34:25 +0400 |
commit | f1bbc1cd19d0d81fee5433efcb570a8845172241 (patch) | |
tree | 2e5a6b7808116456b4baea44ae15f69bbe1e24e8 | |
parent | 8c5d323326d9d527e9a5e08c69eb6085953eb130 (diff) | |
download | mariadb-git-f1bbc1cd19d0d81fee5433efcb570a8845172241.tar.gz |
MDEV-28545 MyISAM reorganize partition corrupt older table format
The ALTER related code cannot do at the same time both:
- modify partitions
- change column data types
Explicit changing of a column data type together with a partition change is
prohibited by the parter, so this is not allowed and returns a syntax error:
ALTER TABLE t MODIFY ts BIGINT, DROP PARTITION p1;
This fix additionally disables implicit data type upgrade
(e.g. from "MariaDB 5.3 TIME" to "MySQL 5.6 TIME", or the other way
around according to the current mysql56_temporal_format) in case of
an ALTER modifying partitions, e.g.:
ALTER TABLE t DROP PARTITION p1;
In such commands now only the partition change happens, while
the data types stay unchanged.
One can additionally run:
ALTER TABLE t FORCE;
either before or after the ALTER modifying partitions to
upgrade data types according to mysql56_temporal_format.
-rw-r--r-- | mysql-test/main/partition_alter.result | 23 | ||||
-rw-r--r-- | mysql-test/main/partition_alter.test | 26 | ||||
-rw-r--r-- | sql/field.cc | 2 | ||||
-rw-r--r-- | sql/field.h | 7 | ||||
-rw-r--r-- | sql/sql_insert.cc | 10 | ||||
-rw-r--r-- | sql/sql_table.cc | 12 |
6 files changed, 78 insertions, 2 deletions
diff --git a/mysql-test/main/partition_alter.result b/mysql-test/main/partition_alter.result index 2b0a09d2653..37e975deb0e 100644 --- a/mysql-test/main/partition_alter.result +++ b/mysql-test/main/partition_alter.result @@ -212,3 +212,26 @@ test.t check status OK delete from t order by b limit 1; drop table t; # End of 10.3 tests +# +# Start of 10.4 tests +# +# +# MDEV-28545 MyISAM reorganize partition corrupt older table format +# +SET GLOBAL mysql56_temporal_format=OFF; +CREATE TABLE t (ts timestamp, KEY (ts)) ENGINE=MyISAM +PARTITION BY RANGE (unix_timestamp(ts)) ( +PARTITION p1 VALUES LESS THAN (1645398000), +PARTITION pn VALUES LESS THAN MAXVALUE +); +SET GLOBAL mysql56_temporal_format=ON; +FLUSH TABLES; +ALTER TABLE t DROP PARTITION p1; +CHECK TABLE t; +Table Op Msg_type Msg_text +test.t check status OK +DROP TABLE t; +SET GLOBAL mysql56_temporal_format=DEFAULT; +# +# End of 10.4 tests +# diff --git a/mysql-test/main/partition_alter.test b/mysql-test/main/partition_alter.test index 7a80779e386..23ad5ece0e4 100644 --- a/mysql-test/main/partition_alter.test +++ b/mysql-test/main/partition_alter.test @@ -197,3 +197,29 @@ delete from t order by b limit 1; drop table t; --echo # End of 10.3 tests + +--echo # +--echo # Start of 10.4 tests +--echo # + +--echo # +--echo # MDEV-28545 MyISAM reorganize partition corrupt older table format +--echo # + +SET GLOBAL mysql56_temporal_format=OFF; +CREATE TABLE t (ts timestamp, KEY (ts)) ENGINE=MyISAM +PARTITION BY RANGE (unix_timestamp(ts)) ( + PARTITION p1 VALUES LESS THAN (1645398000), + PARTITION pn VALUES LESS THAN MAXVALUE +); + +SET GLOBAL mysql56_temporal_format=ON; +FLUSH TABLES; +ALTER TABLE t DROP PARTITION p1; +CHECK TABLE t; +DROP TABLE t; +SET GLOBAL mysql56_temporal_format=DEFAULT; + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/sql/field.cc b/sql/field.cc index 853b0c62f14..bf27780e776 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -11020,8 +11020,6 @@ Column_definition::Column_definition(THD *thd, Field *old_field, type_handler()->Column_definition_reuse_fix_attributes(thd, this, old_field); - type_handler()->Column_definition_implicit_upgrade(this); - /* Copy the default (constant/function) from the column object orig_field, if supplied. We do this if all these conditions are met: diff --git a/sql/field.h b/sql/field.h index 7534a506edc..9d40caf0932 100644 --- a/sql/field.h +++ b/sql/field.h @@ -5203,6 +5203,13 @@ public: bool vers_check_timestamp(const Lex_table_name &table_name) const; bool vers_check_bigint(const Lex_table_name &table_name) const; + + static void upgrade_data_types(List<Create_field> &list) + { + List_iterator<Create_field> it(list); + while (Create_field *f= it++) + f->type_handler()->Column_definition_implicit_upgrade(f); + } }; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index aeb39871025..76fd6385041 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -4346,6 +4346,16 @@ TABLE *select_create::create_table_from_items(THD *thd, List<Item> *items, alter_info->create_list.push_back(cr_field, thd->mem_root); } + /* + Item*::type_handler() always returns pointers to + type_handler_{time2|datetime2|timestamp2} no matter what + the current mysql56_temporal_format says. + Let's convert them according to mysql56_temporal_format. + QQ: This perhaps should eventually be fixed to have Item*::type_handler() + respect mysql56_temporal_format, and remove the upgrade from here. + */ + Create_field::upgrade_data_types(alter_info->create_list); + if (create_info->check_fields(thd, alter_info, create_table->table_name, create_table->db, diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 6aae927800e..efa5c06dd2a 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -10068,6 +10068,18 @@ do_continue:; set_table_default_charset(thd, create_info, alter_ctx.db); + /* + The ALTER related code cannot alter partitions and change column data types + at the same time. So in case of partition change statements like: + ALTER TABLE t1 DROP PARTITION p1; + we skip implicit data type upgrade (such as "MariaDB 5.3 TIME" to + "MySQL 5.6 TIME" or vice versa according to mysql56_temporal_format). + Note, one can run a separate "ALTER TABLE t1 FORCE;" statement + before or after the partition change ALTER statement to upgrade data types. + */ + if (IF_PARTITIONING(!fast_alter_partition, 1)) + Create_field::upgrade_data_types(alter_info->create_list); + if (create_info->check_fields(thd, alter_info, table_list->table_name, table_list->db) || create_info->fix_period_fields(thd, alter_info)) |