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