From 0c346f604019f605e6dc56dfd6d1399de96065c7 Mon Sep 17 00:00:00 2001 From: DandreChen Date: Fri, 6 Jan 2023 16:54:18 +0800 Subject: [PATCH] fix(tianmu): fix alter table add column not null.(#1188) Convert alter table add column not null to use copy algorithm. --- mysql-test/suite/tianmu/r/alter_column.result | 19 +++++++++- mysql-test/suite/tianmu/t/alter_column.test | 19 +++++++++- storage/tianmu/handler/ha_tianmu.cpp | 37 +++++++++++++++++-- storage/tianmu/handler/ha_tianmu.h | 1 + 4 files changed, 70 insertions(+), 6 deletions(-) diff --git a/mysql-test/suite/tianmu/r/alter_column.result b/mysql-test/suite/tianmu/r/alter_column.result index 6f7aa498a4..c641e88077 100644 --- a/mysql-test/suite/tianmu/r/alter_column.result +++ b/mysql-test/suite/tianmu/r/alter_column.result @@ -70,7 +70,7 @@ description VARCHAR(200) NULL, PRIMARY KEY (task_id) ); ALTER TABLE st2 ADD COLUMN col_name3 int auto_increment; -ERROR HY000: AUTO_INCREMENT can be only declared on primary key column! +ERROR 42000: AUTO_INCREMENT can be only declared on primary key column! SHOW CREATE TABLE st2; Table Create Table st2 CREATE TABLE `st2` ( @@ -81,4 +81,21 @@ st2 CREATE TABLE `st2` ( `description` varchar(200) DEFAULT NULL, PRIMARY KEY (`task_id`) ) ENGINE=TIANMU DEFAULT CHARSET=latin1 +CREATE TABLE ttb1( +id int, +name varchar(5) +) ENGINE=TIANMU; +INSERT INTO ttb1 VALUES(1,'AAA'),(2,'BBB'); +ALTER TABLE ttb1 ADD COLUMN age VARCHAR(5) NOT NULL; +SHOW CREATE TABLE ttb1; +Table Create Table +ttb1 CREATE TABLE `ttb1` ( + `id` int(11) DEFAULT NULL, + `name` varchar(5) DEFAULT NULL, + `age` varchar(5) NOT NULL +) ENGINE=TIANMU DEFAULT CHARSET=latin1 +SELECT * FROM ttb1; +id name age +1 AAA +2 BBB DROP DATABASE alter_colunm; diff --git a/mysql-test/suite/tianmu/t/alter_column.test b/mysql-test/suite/tianmu/t/alter_column.test index 81e68b07df..dec0167dda 100644 --- a/mysql-test/suite/tianmu/t/alter_column.test +++ b/mysql-test/suite/tianmu/t/alter_column.test @@ -89,11 +89,28 @@ CREATE TABLE st2 ( PRIMARY KEY (task_id) ); ---error 6 +--error 1075 ALTER TABLE st2 ADD COLUMN col_name3 int auto_increment; SHOW CREATE TABLE st2; +################# +# ADD COLUMN NOT NULL +################# + +CREATE TABLE ttb1( + id int, + name varchar(5) +) ENGINE=TIANMU; + +INSERT INTO ttb1 VALUES(1,'AAA'),(2,'BBB'); + +ALTER TABLE ttb1 ADD COLUMN age VARCHAR(5) NOT NULL; + +SHOW CREATE TABLE ttb1; + +SELECT * FROM ttb1; + ################# # CLEAR UP ################# diff --git a/storage/tianmu/handler/ha_tianmu.cpp b/storage/tianmu/handler/ha_tianmu.cpp index 31a09056a2..c33d1b9606 100644 --- a/storage/tianmu/handler/ha_tianmu.cpp +++ b/storage/tianmu/handler/ha_tianmu.cpp @@ -1579,6 +1579,28 @@ int ha_tianmu::reset() { DBUG_RETURN(ret); } +bool ha_tianmu::check_if_notnull_of_added_column(TABLE *altered_table, Alter_inplace_info *ha_alter_info) { + std::vector old_cols(table_share->field, table_share->field + table_share->fields); + std::vector new_cols(altered_table->s->field, altered_table->s->field + altered_table->s->fields); + + for (size_t i = 0; i < new_cols.size(); i++) { + size_t j; + for (j = 0; j < old_cols.size(); j++) + if (old_cols[j] != nullptr && std::strcmp(new_cols[i]->field_name, old_cols[j]->field_name) == 0) { + old_cols[j] = nullptr; + break; + } + + if (j < old_cols.size()) // column exists + continue; + + if ((*new_cols[i]).null_bit == 0) + return true; + } + + return false; +} + enum_alter_inplace_result ha_tianmu::check_if_supported_inplace_alter([[maybe_unused]] TABLE *altered_table, Alter_inplace_info *ha_alter_info) { DBUG_ENTER(__PRETTY_FUNCTION__); @@ -1594,8 +1616,15 @@ enum_alter_inplace_result ha_tianmu::check_if_supported_inplace_alter([[maybe_un DBUG_RETURN(HA_ALTER_INPLACE_EXCLUSIVE_LOCK); } + // use copy when add column with not null + if((ha_alter_info->handler_flags & Alter_inplace_info::ADD_COLUMN) && + check_if_notnull_of_added_column(altered_table, ha_alter_info)) { + DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); + } + if ((ha_alter_info->handler_flags & ~TIANMU_SUPPORTED_ALTER_ADD_DROP_ORDER) && - (ha_alter_info->handler_flags != TIANMU_SUPPORTED_ALTER_COLUMN_NAME)) { + ((ha_alter_info->handler_flags != TIANMU_SUPPORTED_ALTER_COLUMN_NAME) || + (ha_alter_info->handler_flags & Alter_inplace_info::ALTER_COLUMN_NOT_NULLABLE))) { // support alter table: column type if (ha_alter_info->handler_flags & Alter_inplace_info::ALTER_STORED_COLUMN_TYPE) DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); @@ -1612,9 +1641,9 @@ enum_alter_inplace_result ha_tianmu::check_if_supported_inplace_alter([[maybe_un // support alter table: mix add/drop column、order column and other syntaxs to use if (ha_alter_info->handler_flags & TIANMU_SUPPORTED_ALTER_ADD_DROP_ORDER) DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); - if (ha_alter_info->handler_flags & Alter_inplace_info::ADD_PK_INDEX) - DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); - if (ha_alter_info->handler_flags & Alter_inplace_info::DROP_PK_INDEX) + // support alter table: mix add/drop primary key + if (ha_alter_info->handler_flags & Alter_inplace_info::ADD_PK_INDEX || + ha_alter_info->handler_flags & Alter_inplace_info::DROP_PK_INDEX) DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); DBUG_RETURN(HA_ALTER_ERROR); diff --git a/storage/tianmu/handler/ha_tianmu.h b/storage/tianmu/handler/ha_tianmu.h index ba19d3f166..1112964009 100644 --- a/storage/tianmu/handler/ha_tianmu.h +++ b/storage/tianmu/handler/ha_tianmu.h @@ -164,6 +164,7 @@ class ha_tianmu final : public handler { int set_cond_iter(); int fill_row(uchar *buf); int free_share(); + bool check_if_notnull_of_added_column(TABLE *altered_table, Alter_inplace_info *ha_alter_info); std::shared_ptr share_;