From e734f8091bdcdeef0906555f7ac99d94661fefcb Mon Sep 17 00:00:00 2001 From: zhanghongxing <15150573650@163.com> Date: Thu, 16 Feb 2023 15:59:19 +0000 Subject: [PATCH] feat(tianmu):develop some auto_increment function for tianmu(#1201, #1072, #1059) --- .../tianmu/r/init_auto_increment_value.result | 144 ++++++++++++++++++ .../std_data/load_auto_increment_value.txt | 8 + .../tianmu/t/init_auto_increment_value.test | 63 ++++++++ storage/tianmu/core/engine.cpp | 8 +- storage/tianmu/core/engine.h | 4 +- storage/tianmu/core/filter.cpp | 1 + storage/tianmu/core/table_share.cpp | 6 +- storage/tianmu/core/tianmu_attr.cpp | 8 +- storage/tianmu/core/tianmu_attr.h | 3 +- storage/tianmu/core/tianmu_table.cpp | 4 +- storage/tianmu/core/tianmu_table.h | 1 + storage/tianmu/handler/ha_tianmu.cpp | 54 ++++++- 12 files changed, 291 insertions(+), 13 deletions(-) create mode 100644 mysql-test/suite/tianmu/r/init_auto_increment_value.result create mode 100644 mysql-test/suite/tianmu/std_data/load_auto_increment_value.txt create mode 100644 mysql-test/suite/tianmu/t/init_auto_increment_value.test diff --git a/mysql-test/suite/tianmu/r/init_auto_increment_value.result b/mysql-test/suite/tianmu/r/init_auto_increment_value.result new file mode 100644 index 000000000..de00aac1b --- /dev/null +++ b/mysql-test/suite/tianmu/r/init_auto_increment_value.result @@ -0,0 +1,144 @@ +DROP DATABASE IF EXISTS auto_increment_value_db; +CREATE DATABASE auto_increment_value_db; +USE auto_increment_value_db; +CREATE TABLE t_auto_increment_value ( +id int NOT NULL AUTO_INCREMENT, +data VARCHAR(64) DEFAULT NULL, +PRIMARY KEY (id) +) engine=tianmu AUTO_INCREMENT=100; +show create table t_auto_increment_value; +Table Create Table +t_auto_increment_value CREATE TABLE `t_auto_increment_value` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `data` varchar(64) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=TIANMU AUTO_INCREMENT=100 DEFAULT CHARSET=latin1 +insert into t_auto_increment_value (data) values("first"),("middle"),("last"); +select * from t_auto_increment_value; +id data +100 first +101 middle +102 last +show create table t_auto_increment_value; +Table Create Table +t_auto_increment_value CREATE TABLE `t_auto_increment_value` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `data` varchar(64) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=TIANMU AUTO_INCREMENT=103 DEFAULT CHARSET=latin1 +update t_auto_increment_value set id=80 where id=100; +select * from t_auto_increment_value; +id data +80 first +101 middle +102 last +show create table t_auto_increment_value; +Table Create Table +t_auto_increment_value CREATE TABLE `t_auto_increment_value` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `data` varchar(64) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=TIANMU AUTO_INCREMENT=103 DEFAULT CHARSET=latin1 +insert into t_auto_increment_value (id, data) values(0,"update_lt_max_id"); +select * from t_auto_increment_value; +id data +80 first +101 middle +102 last +103 update_lt_max_id +update t_auto_increment_value set id=200 where id=101; +select * from t_auto_increment_value; +id data +80 first +200 middle +102 last +103 update_lt_max_id +show create table t_auto_increment_value; +Table Create Table +t_auto_increment_value CREATE TABLE `t_auto_increment_value` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `data` varchar(64) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=TIANMU AUTO_INCREMENT=201 DEFAULT CHARSET=latin1 +insert into t_auto_increment_value (id, data) values(0,"update_gt_max_id"); +select * from t_auto_increment_value; +id data +80 first +200 middle +102 last +103 update_lt_max_id +201 update_gt_max_id +alter table t_auto_increment_value AUTO_INCREMENT=300; +select * from t_auto_increment_value; +id data +80 first +200 middle +102 last +103 update_lt_max_id +201 update_gt_max_id +show create table t_auto_increment_value; +Table Create Table +t_auto_increment_value CREATE TABLE `t_auto_increment_value` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `data` varchar(64) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=TIANMU AUTO_INCREMENT=300 DEFAULT CHARSET=latin1 +insert into t_auto_increment_value (id, data) values(0,"alter_gt_max_id"); +select * from t_auto_increment_value; +id data +80 first +200 middle +102 last +103 update_lt_max_id +201 update_gt_max_id +300 alter_gt_max_id +alter table t_auto_increment_value AUTO_INCREMENT=50; +select * from t_auto_increment_value; +id data +80 first +200 middle +102 last +103 update_lt_max_id +201 update_gt_max_id +300 alter_gt_max_id +show create table t_auto_increment_value; +Table Create Table +t_auto_increment_value CREATE TABLE `t_auto_increment_value` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `data` varchar(64) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=TIANMU AUTO_INCREMENT=301 DEFAULT CHARSET=latin1 +insert into t_auto_increment_value (id, data) values(0,"alter_lt_max_id"); +select * from t_auto_increment_value; +id data +80 first +200 middle +102 last +103 update_lt_max_id +201 update_gt_max_id +300 alter_gt_max_id +301 alter_lt_max_id +CREATE TABLE load_auto_increment_value ( +id int(11) NOT NULL AUTO_INCREMENT, +company varchar(25), +PRIMARY KEY (id) +) ENGINE=TIANMU AUTO_INCREMENT=100; +LOAD DATA LOCAL INFILE 'MYSQL_TEST_DIR/suite/tianmu/std_data/load_auto_increment_value.txt' INTO TABLE load_auto_increment_value; +select * from load_auto_increment_value; +id company +100 "syz100" +101 "syz101" +102 "syz102" +103 "syz103" +104 "syz104" +105 "syz105" +106 "syz106" +107 "syz107" +show create table load_auto_increment_value; +Table Create Table +load_auto_increment_value CREATE TABLE `load_auto_increment_value` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `company` varchar(25) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=TIANMU AUTO_INCREMENT=108 DEFAULT CHARSET=latin1 +DROP DATABASE auto_increment_value_db; diff --git a/mysql-test/suite/tianmu/std_data/load_auto_increment_value.txt b/mysql-test/suite/tianmu/std_data/load_auto_increment_value.txt new file mode 100644 index 000000000..8d32b3ff9 --- /dev/null +++ b/mysql-test/suite/tianmu/std_data/load_auto_increment_value.txt @@ -0,0 +1,8 @@ +0;"syz100" +0;"syz101" +0;"syz102" +0;"syz103" +0;"syz104" +0;"syz105" +0;"syz106" +0;"syz107" diff --git a/mysql-test/suite/tianmu/t/init_auto_increment_value.test b/mysql-test/suite/tianmu/t/init_auto_increment_value.test new file mode 100644 index 000000000..a817e009e --- /dev/null +++ b/mysql-test/suite/tianmu/t/init_auto_increment_value.test @@ -0,0 +1,63 @@ +--source include/have_tianmu.inc +# +# Test auto_increment_value with TIANMU +# +--disable_warnings +DROP DATABASE IF EXISTS auto_increment_value_db; +--enable_warnings + +CREATE DATABASE auto_increment_value_db; +USE auto_increment_value_db; + +# test init value +CREATE TABLE t_auto_increment_value ( + id int NOT NULL AUTO_INCREMENT, + data VARCHAR(64) DEFAULT NULL, + PRIMARY KEY (id) +) engine=tianmu AUTO_INCREMENT=100; +show create table t_auto_increment_value; +insert into t_auto_increment_value (data) values("first"),("middle"),("last"); +select * from t_auto_increment_value; +show create table t_auto_increment_value; + +# test update +update t_auto_increment_value set id=80 where id=100; +select * from t_auto_increment_value; +show create table t_auto_increment_value; +insert into t_auto_increment_value (id, data) values(0,"update_lt_max_id"); +select * from t_auto_increment_value; + +update t_auto_increment_value set id=200 where id=101; +select * from t_auto_increment_value; +show create table t_auto_increment_value; +insert into t_auto_increment_value (id, data) values(0,"update_gt_max_id"); +select * from t_auto_increment_value; + +# test alter +alter table t_auto_increment_value AUTO_INCREMENT=300; +select * from t_auto_increment_value; +show create table t_auto_increment_value; +insert into t_auto_increment_value (id, data) values(0,"alter_gt_max_id"); +select * from t_auto_increment_value; + +# when SET AUTO_INCREMENT < max_id, AUTO_INCREMENT value wouldnot be changed. +alter table t_auto_increment_value AUTO_INCREMENT=50; +select * from t_auto_increment_value; +show create table t_auto_increment_value; +insert into t_auto_increment_value (id, data) values(0,"alter_lt_max_id"); +select * from t_auto_increment_value; + + +#test load data with auto_increment value into auto_increment col +CREATE TABLE load_auto_increment_value ( + id int(11) NOT NULL AUTO_INCREMENT, + company varchar(25), + PRIMARY KEY (id) + ) ENGINE=TIANMU AUTO_INCREMENT=100; +--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR +eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/tianmu/std_data/load_auto_increment_value.txt' INTO TABLE load_auto_increment_value; +select * from load_auto_increment_value; +show create table load_auto_increment_value; + +# Clean UP +DROP DATABASE auto_increment_value_db; diff --git a/storage/tianmu/core/engine.cpp b/storage/tianmu/core/engine.cpp index 28dc08438..bfd121a44 100644 --- a/storage/tianmu/core/engine.cpp +++ b/storage/tianmu/core/engine.cpp @@ -877,7 +877,8 @@ uint32_t Engine::GetNextTableId() { return seq; } -std::shared_ptr Engine::GetTableOption(const std::string &table, TABLE *form) { +std::shared_ptr Engine::GetTableOption(const std::string &table, TABLE *form, + HA_CREATE_INFO *create_info) { auto opt = std::make_shared(); int power = has_pack(form->s->comment); @@ -895,10 +896,13 @@ std::shared_ptr Engine::GetTableOption(const std::string &table, TA opt->path = table + common::TIANMU_EXT; opt->name = form->s->table_name.str; + opt->create_info = create_info; return opt; } -void Engine::CreateTable(const std::string &table, TABLE *form) { TianmuTable::CreateNew(GetTableOption(table, form)); } +void Engine::CreateTable(const std::string &table, TABLE *form, HA_CREATE_INFO *create_info) { + TianmuTable::CreateNew(GetTableOption(table, form, create_info)); +} AttributeTypeInfo Engine::GetAttrTypeInfo(const Field &field) { bool auto_inc = field.flags & AUTO_INCREMENT_FLAG; diff --git a/storage/tianmu/core/engine.h b/storage/tianmu/core/engine.h index dd009864d..581e51508 100644 --- a/storage/tianmu/core/engine.h +++ b/storage/tianmu/core/engine.h @@ -79,7 +79,7 @@ class Engine final { ~Engine(); int Init(uint engine_slot); - void CreateTable(const std::string &table, TABLE *from); + void CreateTable(const std::string &table, TABLE *from, HA_CREATE_INFO *create_info); int DeleteTable(const char *table, THD *thd); void TruncateTable(const std::string &table_path, THD *thd); int RenameTable(Transaction *trans_, const std::string &from, const std::string &to, THD *thd); @@ -182,7 +182,7 @@ class Engine final { static std::unique_ptr CreateIOParameters(const std::string &path, void *arg); static std::unique_ptr CreateIOParameters(THD *thd, TABLE *table, void *arg); void LogStat(); - std::shared_ptr GetTableOption(const std::string &table, TABLE *form); + std::shared_ptr GetTableOption(const std::string &table, TABLE *form, HA_CREATE_INFO *create_info); std::shared_ptr getTableShare(const std::string &table_path); std::unique_ptr GetRecord(size_t &len); diff --git a/storage/tianmu/core/filter.cpp b/storage/tianmu/core/filter.cpp index 0f97d6e6e..8f78bf86b 100644 --- a/storage/tianmu/core/filter.cpp +++ b/storage/tianmu/core/filter.cpp @@ -16,6 +16,7 @@ */ #include "filter.h" + #include "common/assert.h" #include "core/tools.h" diff --git a/storage/tianmu/core/table_share.cpp b/storage/tianmu/core/table_share.cpp index c324ece34..d586b142a 100644 --- a/storage/tianmu/core/table_share.cpp +++ b/storage/tianmu/core/table_share.cpp @@ -47,10 +47,10 @@ TableShare::TableShare(const fs::path &table_path, const TABLE_SHARE *table_shar for (uint i = 0; i < no_cols; i++) { common::TX_ID xid; fv.ReadExact(&xid, sizeof(xid)); - m_columns.emplace_back(std::make_unique( - this, xid, i, table_path / common::COLUMN_DIR / std::to_string(i), table_share->field[i])); + Field *field = table_share->field[i]; + auto colpath = table_path / common::COLUMN_DIR / std::to_string(i); + m_columns.emplace_back(std::make_unique(this, xid, i, colpath, field)); } - thr_lock_init(&thr_lock); } diff --git a/storage/tianmu/core/tianmu_attr.cpp b/storage/tianmu/core/tianmu_attr.cpp index c0d11e1b5..707eef22a 100644 --- a/storage/tianmu/core/tianmu_attr.cpp +++ b/storage/tianmu/core/tianmu_attr.cpp @@ -63,7 +63,8 @@ TianmuAttr::TianmuAttr(Transaction *tx, common::TX_ID xid, int a_num, int t_num, }; } -void TianmuAttr::Create(const fs::path &dir, const AttributeTypeInfo &ati, uint8_t pss, size_t no_rows) { +void TianmuAttr::Create(const fs::path &dir, const AttributeTypeInfo &ati, uint8_t pss, size_t no_rows, + uint64_t auto_inc_value) { uint32_t no_pack = common::rows2packs(no_rows, pss); // write meta data(immutable) @@ -108,6 +109,11 @@ void TianmuAttr::Create(const fs::path &dir, const AttributeTypeInfo &ati, uint8 dict->SaveData(dir / common::COL_DICT_DIR / std::to_string(1)); } + // auto_increment + if (ati.AutoInc() && auto_inc_value != 0) { + hdr.auto_inc_next = --auto_inc_value; + } + // create version directory fs::create_directory(dir / common::COL_VERSION_DIR); diff --git a/storage/tianmu/core/tianmu_attr.h b/storage/tianmu/core/tianmu_attr.h index 1c3f76b11..ad18d5b99 100644 --- a/storage/tianmu/core/tianmu_attr.h +++ b/storage/tianmu/core/tianmu_attr.h @@ -87,7 +87,8 @@ class TianmuAttr final : public mm::TraceableObject, public PhysicalColumn, publ TianmuAttr &operator=(const TianmuAttr &) = delete; ~TianmuAttr() = default; - static void Create(const fs::path &path, const AttributeTypeInfo &ati, uint8_t pss, size_t no_rows); + static void Create(const fs::path &path, const AttributeTypeInfo &ati, uint8_t pss, size_t no_rows, + uint64_t auto_inc_value = 0); mm::TO_TYPE TraceableType() const override { return mm::TO_TYPE::TO_TEMPORARY; } void UpdateData(uint64_t row, Value &old_v, Value &new_v); diff --git a/storage/tianmu/core/tianmu_table.cpp b/storage/tianmu/core/tianmu_table.cpp index f384b48a1..67c9310dc 100644 --- a/storage/tianmu/core/tianmu_table.cpp +++ b/storage/tianmu/core/tianmu_table.cpp @@ -361,7 +361,7 @@ void TianmuTable::CreateNew(const std::shared_ptr &opt) { uint32_t tid = ha_tianmu_engine_->GetNextTableId(); auto &path(opt->path); uint32_t no_attrs = opt->atis.size(); - + uint64_t auto_inc_value = opt->create_info->auto_increment_value; fs::create_directory(path); TABLE_META meta{common::FILE_MAGIC, common::TABLE_DATA_VERSION, tid, opt->pss}; @@ -395,7 +395,7 @@ void TianmuTable::CreateNew(const std::shared_ptr &opt) { auto lnk = column_path / std::to_string(idx); fs::create_symlink(dir, lnk); - TianmuAttr::Create(lnk, opt->atis[idx], opt->pss, 0); + TianmuAttr::Create(lnk, opt->atis[idx], opt->pss, 0, auto_inc_value); // TIANMU_LOG(LogCtl_Level::INFO, "Column %zu at %s", idx, dir.c_str()); } TIANMU_LOG(LogCtl_Level::INFO, "Create table %s, ID = %u", opt->path.c_str(), tid); diff --git a/storage/tianmu/core/tianmu_table.h b/storage/tianmu/core/tianmu_table.h index e38dce831..4cc7b9cb5 100644 --- a/storage/tianmu/core/tianmu_table.h +++ b/storage/tianmu/core/tianmu_table.h @@ -49,6 +49,7 @@ struct TableOption { std::string name; int id; uint8_t pss; + HA_CREATE_INFO *create_info; }; class DataPackLock : public FunctionExecutor { diff --git a/storage/tianmu/handler/ha_tianmu.cpp b/storage/tianmu/handler/ha_tianmu.cpp index 68dd838f0..14e52b684 100644 --- a/storage/tianmu/handler/ha_tianmu.cpp +++ b/storage/tianmu/handler/ha_tianmu.cpp @@ -518,7 +518,12 @@ int ha_tianmu::rename_table(const char *from, const char *to) { DBUG_RETURN(1); } -void ha_tianmu::update_create_info([[maybe_unused]] HA_CREATE_INFO *create_info) {} +void ha_tianmu::update_create_info(HA_CREATE_INFO *create_info) { + if (!(create_info->used_fields & HA_CREATE_USED_AUTO)) { + info(HA_STATUS_AUTO); + create_info->auto_increment_value = stats.auto_increment_value; + } +} /* ::info() is used to return information to the optimizer. @@ -598,6 +603,20 @@ int ha_tianmu::info(uint flag) { my_store_ptr(dup_ref, ref_length, dupkey_pos_); } + if ((flag & HA_STATUS_AUTO) && table->found_next_number_field) { + std::shared_ptr tab; + if (current_txn_ != nullptr) { + tab = current_txn_->GetTableByPath(table_name_); + } else { + tab = ha_tianmu_engine_->GetTableRD(table_name_); + } + for (uint colno = 0; colno < tab->NumOfAttrs(); colno++) { + auto attr = tab->GetAttr(colno); + if (attr->GetIfAutoInc()) { + stats.auto_increment_value = attr->GetAutoIncInfo(); + } + } + } ret = 0; } catch (std::exception &e) { my_message(static_cast(common::ErrorCode::UNKNOWN_ERROR), e.what(), MYF(0)); @@ -1178,7 +1197,7 @@ int ha_tianmu::create(const char *name, TABLE *table_arg, [[maybe_unused]] HA_CR DBUG_RETURN(ER_WRONG_TABLE_NAME); } - ha_tianmu_engine_->CreateTable(name, table_arg); + ha_tianmu_engine_->CreateTable(name, table_arg, create_info); DBUG_RETURN(0); } catch (common::AutoIncException &e) { my_message(ER_WRONG_AUTO_KEY, e.what(), MYF(0)); @@ -1489,6 +1508,9 @@ enum_alter_inplace_result ha_tianmu::check_if_supported_inplace_alter([[maybe_un // support alter table comment if (ha_alter_info->create_info->used_fields & HA_CREATE_USED_COMMENT) DBUG_RETURN(HA_ALTER_INPLACE_EXCLUSIVE_LOCK); + // support alter table auto_increment + if (ha_alter_info->create_info->used_fields & HA_CREATE_USED_AUTO) + DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); } // use copy when add column with not null @@ -1536,6 +1558,32 @@ bool ha_tianmu::inplace_alter_table(TABLE *altered_table, Alter_inplace_info *ha DBUG_RETURN(false); if (ha_alter_info->create_info->used_fields & HA_CREATE_USED_COMMENT) DBUG_RETURN(false); + if (ha_alter_info->create_info->used_fields & HA_CREATE_USED_AUTO) { + auto tab = current_txn_->GetTableByPath(table_name_); + fs::path tab_dir = table_name_ + common::TIANMU_EXT; + for (uint i = 0; i < table_share->fields; i++) { + if (table_share->field[i]->flags & AUTO_INCREMENT_FLAG) { + system::TianmuFile fv, fw; + fv.OpenReadOnly(tab_dir / common::TABLE_VERSION_FILE); + common::TX_ID xid; + fv.ReadExact(&xid, sizeof(xid)); + Tianmu::core::COL_VER_HDR hdr{}; + fs::path fname = + tab_dir / common::COLUMN_DIR / std::to_string(i) / common::COL_VERSION_DIR / xid.ToString(); + fw.OpenReadWrite(fname); + fw.ReadExact(&hdr, sizeof(hdr)); + uint64_t autoinc_ = ha_alter_info->create_info->auto_increment_value; + if (autoinc_ > hdr.auto_inc_next) { // alter table auto_increment must be > current max autoinc + hdr.auto_inc_next = --autoinc_; + fw.WriteExact(&hdr, sizeof(hdr)); + } + fw.Flush(); + } + } + ha_tianmu_engine_->cache.ReleaseTable(tab->GetID()); + ha_tianmu_engine_->UnRegisterTable(table_name_); + DBUG_RETURN(false); + } } else if (!(ha_alter_info->handler_flags & ~TIANMU_SUPPORTED_ALTER_ADD_DROP_ORDER)) { std::vector v_old(table_share->field, table_share->field + table_share->fields); std::vector v_new(altered_table->s->field, altered_table->s->field + altered_table->s->fields); @@ -1574,6 +1622,8 @@ bool ha_tianmu::commit_inplace_alter_table([[maybe_unused]] TABLE *altered_table DBUG_RETURN(false); if (ha_alter_info->create_info->used_fields & HA_CREATE_USED_COMMENT) DBUG_RETURN(false); + if (ha_alter_info->create_info->used_fields & HA_CREATE_USED_AUTO) + DBUG_RETURN(false); } if (ha_alter_info->handler_flags == TIANMU_SUPPORTED_ALTER_COLUMN_NAME) { DBUG_RETURN(false);