From df74bd033c8d3be20a0761a076216cd0f91de1f5 Mon Sep 17 00:00:00 2001 From: lepsa <3124026032@qq.com> Date: Sat, 6 Jul 2024 11:26:30 +0800 Subject: [PATCH] test:update insert --- src/execution/executor_insert.h | 64 +++++++++++++++--------- src/execution/executor_update.h | 87 +++++++++++++++++++-------------- 2 files changed, 89 insertions(+), 62 deletions(-) diff --git a/src/execution/executor_insert.h b/src/execution/executor_insert.h index 41d1229..2abe37b 100644 --- a/src/execution/executor_insert.h +++ b/src/execution/executor_insert.h @@ -38,49 +38,65 @@ class InsertExecutor : public AbstractExecutor { context_ = context; }; - std::unique_ptr<RmRecord> Next() override { - // Make record buffer + std::unique_ptr<RmRecord> Next() override { + // 创建记录缓冲区 RmRecord rec(fh_->get_file_hdr().record_size); - std::vector<Rid> result; + + prepareRecordData(rec); + checkForDuplicateKeys(rec); + + // æ’入记录到文件 + rid_ = fh_->insert_record(rec.data, context_); + + insertIntoIndexes(rec); + + return nullptr; + } + + Rid &rid() override { return rid_; } + + private: + void prepareRecordData(RmRecord& rec) { for (size_t i = 0; i < values_.size(); i++) { - auto &col = tab_.cols[i]; - auto &val = values_[i]; - if(val.type == TYPE_INT && col.type == TYPE_FLOAT){ + auto& col = tab_.cols[i]; + auto& val = values_[i]; + + if (val.type == TYPE_INT && col.type == TYPE_FLOAT) { val.set_float(val.int_val); - }else if(val.type == TYPE_FLOAT && col.type == TYPE_INT){ + } else if (val.type == TYPE_FLOAT && col.type == TYPE_INT) { val.set_int(val.float_val); } + if (col.type != val.type) { throw IncompatibleTypeError(coltype2str(col.type), coltype2str(val.type)); } + val.init_raw(col.len); memcpy(rec.data + col.offset, val.raw->data, col.len); } - // Check if index is same - for(size_t i = 0; i<tab_.indexes.size(); ++i){ - auto &index = tab_.indexes[i]; + } + + void checkForDuplicateKeys(const RmRecord& rec) { + std::vector<Rid> result; + for (const auto& index : tab_.indexes) { auto ih = sm_manager_->ihs_.at(index.index_name).get(); auto insert_key = index.get_key(rec.data); - if(ih->get_value(insert_key.get(),&result,context_->txn_)){ + if (ih->get_value(insert_key.get(), &result, context_->txn_)) { throw DuplicateKeyError(index.index_name); } } - // Insert into record file - rid_ = fh_->insert_record(rec.data, context_); - - // Insert into index - for(size_t i = 0; i < tab_.indexes.size(); ++i) { - auto& index = tab_.indexes[i]; + } + + void insertIntoIndexes(const RmRecord& rec) { + for (const auto& index : tab_.indexes) { auto ih = sm_manager_->ihs_.at(sm_manager_->get_ix_manager()->get_index_name(tab_name_, index.cols)).get(); - char* key = new char[index.col_tot_len]; + std::unique_ptr<char[]> key(new char[index.col_tot_len]); int offset = 0; - for(size_t i = 0; i < index.col_num; ++i) { - memcpy(key + offset, rec.data + index.cols[i].offset, index.cols[i].len); - offset += index.cols[i].len; + for (const auto& col : index.cols) { + memcpy(key.get() + offset, rec.data + col.offset, col.len); + offset += col.len; } - ih->insert_entry(key, rid_, context_->txn_); + ih->insert_entry(key.get(), rid_, context_->txn_); } - return nullptr; } - Rid &rid() override { return rid_; } }; \ No newline at end of file diff --git a/src/execution/executor_update.h b/src/execution/executor_update.h index aa4348c..fc9397c 100644 --- a/src/execution/executor_update.h +++ b/src/execution/executor_update.h @@ -42,65 +42,76 @@ class UpdateExecutor : public AbstractExecutor { std::unique_ptr<RmRecord> Next() override { int record_size = fh_->get_file_hdr().record_size; auto buf = std::make_unique<char[]>(record_size); + for (const auto &rid: rids_) { std::unique_ptr<RmRecord> record = fh_->get_record(rid, context_); memcpy(buf.get(), record->data, record_size); - for (auto &clause: set_clauses_) { - std::vector<ColMeta>::iterator col = tab_.get_col(clause.lhs.col_name); - clause.rhs.init_raw(col->len); - memcpy(buf.get() + col->offset, clause.rhs.raw->data, col->len); - } + + applySetClauses(buf.get()); RmRecord old_record{record->size}; RmRecord new_record{record->size}; memcpy(old_record.data, record->data, record->size); memcpy(new_record.data, buf.get(), record->size); - // 检查更新主键 - for (size_t i = 0; i < tab_.indexes.size(); ++i) { - auto &index = tab_.indexes[i]; - auto ih = sm_manager_->ihs_.at(index.index_name).get(); - auto old_key = index.get_key(old_record.data); - auto insert_key = index.get_key(new_record.data); - if (memcmp(old_key.get(), insert_key.get(), index.col_tot_len) == 0) { - continue; - } + + checkForPrimaryKeyUpdate(old_record, new_record); + + fh_->update_record(rid, buf.get(), context_); + updateIndexes(old_record, new_record, rid); + } + return nullptr; + } + + Rid &rid() override { return _abstract_rid; } + +private: + void applySetClauses(char *buf) { + for (auto &clause: set_clauses_) { + auto col = tab_.get_col(clause.lhs.col_name); + clause.rhs.init_raw(col->len); + memcpy(buf + col->offset, clause.rhs.raw->data, col->len); + } + } + + void checkForPrimaryKeyUpdate(const RmRecord &old_record, const RmRecord &new_record) { + for (const auto &index : tab_.indexes) { + auto ih = sm_manager_->ihs_.at(index.index_name).get(); + auto old_key = index.get_key(old_record.data); + auto new_key = index.get_key(new_record.data); + + if (memcmp(old_key.get(), new_key.get(), index.col_tot_len) != 0) { std::vector<Rid> result; - if (ih->get_value(insert_key.get(), &result, context_->txn_)) { + if (ih->get_value(new_key.get(), &result, context_->txn_)) { throw DuplicateKeyError(index.index_name); } } - - // æ›´æ–°record - fh_->update_record(rid, buf.get(), context_); + } + } - // 在 index 䏿›´æ–° - for(size_t i = 0; i < tab_.indexes.size(); ++i) { - auto& index = tab_.indexes[i]; - auto const &cols = index.cols; - // éœ€è¦ update çš„å—æ®µæ˜¯å¦åœ¨ç´¢å¼•ä¸å‡ºçް - bool need_update = false; - for (auto const &set_clause : set_clauses_) { - auto pos = std::find_if(cols.begin(), cols.end(), [&set_clause](const ColMeta &col) { - return col.name == set_clause.lhs.col_name; - }); - if (pos != cols.end()) { - need_update = true; - break; - } - } - if (!need_update) { - continue; - } + void updateIndexes(const RmRecord &old_record, const RmRecord &new_record, const Rid &rid) { + for (const auto &index : tab_.indexes) { + if (isIndexUpdated(index)) { auto ih = sm_manager_->ihs_.at(index.index_name).get(); auto delete_key = index.get_key(old_record.data); auto insert_key = index.get_key(new_record.data); + ih->delete_entry(delete_key.get(), context_->txn_); ih->insert_entry(insert_key.get(), rid, context_->txn_); } } - return nullptr; } - Rid &rid() override { return _abstract_rid; } + bool isIndexUpdated(const IndexMeta &index) { + const auto &cols = index.cols; + for (const auto &set_clause : set_clauses_) { + auto pos = std::find_if(cols.begin(), cols.end(), [&set_clause](const ColMeta &col) { + return col.name == set_clause.lhs.col_name; + }); + if (pos != cols.end()) { + return true; + } + } + return false; + } }; \ No newline at end of file -- GitLab