From a774f0c144e981fe83e0c8ae1ea434d1e58c635c Mon Sep 17 00:00:00 2001 From: wuxiaobai24 Date: Fri, 7 Oct 2022 23:57:51 +0800 Subject: [PATCH 1/3] temp commmit --- .gitignore | 1 + src/observer/sql/executor/execute_stage.cpp | 30 +++++++++- src/observer/sql/executor/execute_stage.h | 1 + src/observer/sql/stmt/stmt.cpp | 5 ++ src/observer/sql/stmt/update_stmt.cpp | 63 +++++++++++++++++++-- src/observer/sql/stmt/update_stmt.h | 8 ++- src/observer/storage/common/table.cpp | 12 ++++ src/observer/storage/common/table.h | 2 + 8 files changed, 114 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index c58fa5a01..631bd3755 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,5 @@ GRTAGS GPATH GTAGS .gitmodules +.cache #*# diff --git a/src/observer/sql/executor/execute_stage.cpp b/src/observer/sql/executor/execute_stage.cpp index d1da254ef..4cda073e2 100644 --- a/src/observer/sql/executor/execute_stage.cpp +++ b/src/observer/sql/executor/execute_stage.cpp @@ -32,6 +32,7 @@ See the Mulan PSL v2 for more details. */ #include "sql/operator/predicate_operator.h" #include "sql/operator/delete_operator.h" #include "sql/operator/project_operator.h" +#include "sql/operator/update_operator.h" #include "sql/stmt/stmt.h" #include "sql/stmt/select_stmt.h" #include "sql/stmt/update_stmt.h" @@ -142,7 +143,7 @@ void ExecuteStage::handle_request(common::StageEvent *event) do_insert(sql_event); } break; case StmtType::UPDATE: { - //do_update((UpdateStmt *)stmt, session_event); + do_update(sql_event); } break; case StmtType::DELETE: { do_delete(sql_event); @@ -438,6 +439,33 @@ RC ExecuteStage::do_select(SQLStageEvent *sql_event) return rc; } +RC ExecuteStage::do_update(SQLStageEvent *sql_event) +{ + LOG_WARN("do update"); + Stmt *stmt = sql_event->stmt(); + SessionEvent *session_event = sql_event->session_event(); + + if (stmt == nullptr) { + LOG_WARN("cannot find statement"); + return RC::GENERIC_ERROR; + } + + UpdateStmt *update_stmt = (UpdateStmt *)stmt; + TableScanOperator scan_oper(update_stmt->table()); + PredicateOperator pred_oper(update_stmt->filter_stmt()); + pred_oper.add_child(&scan_oper); + UpdateOperator update_oper(update_stmt); + update_oper.add_child(&pred_oper); + + RC rc = update_oper.open(); + if (rc != RC::SUCCESS) { + session_event->set_response("FAILURE\n"); + } else { + session_event->set_response("SUCCESS\n"); + } + return rc; +} + RC ExecuteStage::do_help(SQLStageEvent *sql_event) { SessionEvent *session_event = sql_event->session_event(); diff --git a/src/observer/sql/executor/execute_stage.h b/src/observer/sql/executor/execute_stage.h index 9444bb0b8..2e03a1f82 100644 --- a/src/observer/sql/executor/execute_stage.h +++ b/src/observer/sql/executor/execute_stage.h @@ -48,6 +48,7 @@ class ExecuteStage : public common::Stage { RC do_insert(SQLStageEvent *sql_event); RC do_delete(SQLStageEvent *sql_event); RC do_drop_table(SQLStageEvent *sql_event); + RC do_update(SQLStageEvent *sql_event); protected: private: diff --git a/src/observer/sql/stmt/stmt.cpp b/src/observer/sql/stmt/stmt.cpp index 81185c1cc..62f909eee 100644 --- a/src/observer/sql/stmt/stmt.cpp +++ b/src/observer/sql/stmt/stmt.cpp @@ -14,9 +14,11 @@ See the Mulan PSL v2 for more details. */ #include "rc.h" #include "common/log/log.h" +#include "sql/parser/parse_defs.h" #include "sql/stmt/insert_stmt.h" #include "sql/stmt/delete_stmt.h" #include "sql/stmt/select_stmt.h" +#include "sql/stmt/update_stmt.h" RC Stmt::create_stmt(Db *db, const Query &query, Stmt *&stmt) { @@ -33,6 +35,9 @@ RC Stmt::create_stmt(Db *db, const Query &query, Stmt *&stmt) case SCF_SELECT: { return SelectStmt::create(db, query.sstr.selection, stmt); } + case SCF_UPDATE: { + return UpdateStmt::create(db, query.sstr.update, stmt); + } default: { LOG_WARN("unknown query command"); } diff --git a/src/observer/sql/stmt/update_stmt.cpp b/src/observer/sql/stmt/update_stmt.cpp index 89331f54c..aff9d2747 100644 --- a/src/observer/sql/stmt/update_stmt.cpp +++ b/src/observer/sql/stmt/update_stmt.cpp @@ -12,15 +12,66 @@ See the Mulan PSL v2 for more details. */ // Created by Wangyunlai on 2022/5/22. // +#include "common/log/log.h" #include "sql/stmt/update_stmt.h" +#include "sql/stmt/filter_stmt.h" +#include "storage/common/db.h" +#include "storage/common/table.h" -UpdateStmt::UpdateStmt(Table *table, Value *values, int value_amount) - : table_ (table), values_(values), value_amount_(value_amount) +UpdateStmt::UpdateStmt(Table *table, Value *values, int value_amount, FilterStmt *filter_stmt) + : table_ (table), values_(values), value_amount_(value_amount), filter_stmt_(filter_stmt) {} -RC UpdateStmt::create(Db *db, const Updates &update, Stmt *&stmt) +UpdateStmt::~UpdateStmt() { - // TODO - stmt = nullptr; - return RC::INTERNAL; + if (nullptr != filter_stmt_) { + delete filter_stmt_; + filter_stmt_ = nullptr; + } +} + +RC UpdateStmt::create(Db *db, const Updates &update_sql, Stmt *&stmt) +{ + const char *table_name = update_sql.relation_name; + if (nullptr == db || nullptr == table_name) { + LOG_WARN("invalid argument. db=%p, table_name=%p", db, table_name); + return RC::INVALID_ARGUMENT; + } + + // check whether the table exists + Table *table = db->find_table(table_name); + if (nullptr == table) { + LOG_WARN("no such table. db = %s, table = %s", db->name(), table_name); + return RC::SCHEMA_TABLE_NOT_EXIST; + } + + // check the fields exist + const TableMeta &table_meta = table->table_meta(); + const FieldMeta *field_meta = table_meta.field(update_sql.attribute_name); + if (nullptr == field_meta) { + LOG_WARN("no such field. table=%s, field=%s", table_name, update_sql.attribute_name); + return RC::SCHEMA_FIELD_NOT_EXIST; + } + + // check the field type + if (field_meta->type() != update_sql.value.type) { + LOG_WARN("field type not match. field=%s, field_type=%d, value_type=%d", + field_meta->name(), field_meta->type(), update_sql.value.type); + return RC::SCHEMA_FIELD_TYPE_MISMATCH; + } + + std::unordered_map table_map; + table_map.insert(std::pair(std::string(table_name), table)); + + FilterStmt *filter_stmt = nullptr; + RC rc = FilterStmt::create(db, table, &table_map, + update_sql.conditions, update_sql.condition_num, filter_stmt); + if (rc != RC::SUCCESS) { + LOG_WARN("failed to create filter statement. rc=%d:%s", rc, strrc(rc)); + return rc; + } + Value *values = const_cast(&update_sql.value); + stmt = new UpdateStmt(table, values, 1, filter_stmt); + + return RC::SUCCESS; } diff --git a/src/observer/sql/stmt/update_stmt.h b/src/observer/sql/stmt/update_stmt.h index ca566618d..25b9626dd 100644 --- a/src/observer/sql/stmt/update_stmt.h +++ b/src/observer/sql/stmt/update_stmt.h @@ -18,14 +18,17 @@ See the Mulan PSL v2 for more details. */ #include "sql/stmt/stmt.h" class Table; +class FilterStmt; class UpdateStmt : public Stmt { public: UpdateStmt() = default; - UpdateStmt(Table *table, Value *values, int value_amount); + UpdateStmt(Table *table, Value *values, int value_amount, FilterStmt *filter_stmt); + ~UpdateStmt() override; + StmtType type() const override { return StmtType::UPDATE; } public: static RC create(Db *db, const Updates &update_sql, Stmt *&stmt); @@ -34,9 +37,12 @@ class UpdateStmt : public Stmt Value *values() const { return values_; } int value_amount() const { return value_amount_; } + FilterStmt *filter_stmt() const { return filter_stmt_; } + private: Table *table_ = nullptr; Value *values_ = nullptr; int value_amount_ = 0; + FilterStmt *filter_stmt_ = nullptr; }; diff --git a/src/observer/storage/common/table.cpp b/src/observer/storage/common/table.cpp index b3715302b..69ac7c5c7 100644 --- a/src/observer/storage/common/table.cpp +++ b/src/observer/storage/common/table.cpp @@ -731,6 +731,18 @@ RC Table::delete_record(Trx *trx, Record *record) return rc; } +RC Table::update_record(Trx *trx, Record *record) +{ + RC rc = RC::SUCCESS; + if (trx != nullptr) { + // TODO: trx support update record + } else { + // TODO: update entry of indexes + rc = record_handler_->update_record(record); + } + return rc; +} + RC Table::commit_delete(Trx *trx, const RID &rid) { RC rc = RC::SUCCESS; diff --git a/src/observer/storage/common/table.h b/src/observer/storage/common/table.h index c487f4d00..fd875271a 100644 --- a/src/observer/storage/common/table.h +++ b/src/observer/storage/common/table.h @@ -55,6 +55,8 @@ class Table { RC insert_record(Trx *trx, int value_num, const Value *values); RC update_record(Trx *trx, const char *attribute_name, const Value *value, int condition_num, const Condition conditions[], int *updated_count); + RC update_record(Trx *trx, Record *record); + RC update_record(Trx *trx, Record *record, const Value *value); RC delete_record(Trx *trx, ConditionFilter *filter, int *deleted_count); RC delete_record(Trx *trx, Record *record); From 58845296a313ac2554330f522ee7293c1c047834 Mon Sep 17 00:00:00 2001 From: wuxiaobai24 Date: Sat, 8 Oct 2022 00:00:14 +0800 Subject: [PATCH 2/3] add update_operator --- src/observer/sql/operator/update_operator.cpp | 64 +++++++++++++++++++ src/observer/sql/operator/update_operator.h | 42 ++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 src/observer/sql/operator/update_operator.cpp create mode 100644 src/observer/sql/operator/update_operator.h diff --git a/src/observer/sql/operator/update_operator.cpp b/src/observer/sql/operator/update_operator.cpp new file mode 100644 index 000000000..0746ca4cb --- /dev/null +++ b/src/observer/sql/operator/update_operator.cpp @@ -0,0 +1,64 @@ +/* Copyright (c) 2021 Xie Meiyi(xiemeiyi@hust.edu.cn) and OceanBase and/or its affiliates. All rights reserved. +miniob is licensed under Mulan PSL v2. +You can use this software according to the terms and conditions of the Mulan PSL v2. +You may obtain a copy of Mulan PSL v2 at: + http://license.coscl.org.cn/MulanPSL2 +THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +See the Mulan PSL v2 for more details. */ + +// +// Created by wuxiaobai24 on 2022/6/27. +// + +#include "common/log/log.h" +#include "sql/operator/update_operator.h" +#include "storage/record/record.h" +#include "storage/common/table.h" +#include "sql/stmt/update_stmt.h" + +RC UpdateOperator::open() +{ + if (children_.size() != 1) { + LOG_WARN("delete operator must has 1 child"); + return RC::INTERNAL; + } + + Operator *child = children_[0]; + RC rc = child->open(); + if (rc != RC::SUCCESS) { + LOG_WARN("failed to open child operator: %s", strrc(rc)); + return rc; + } + + Table *table = update_stmt_->table(); + while (RC::SUCCESS == (rc = child->next())) { + Tuple *tuple = child->current_tuple(); + if (nullptr == tuple) { + LOG_WARN("failed to get current record: %s", strrc(rc)); + return rc; + } + + RowTuple *row_tuple = static_cast(tuple); + Record &record = row_tuple->record(); + + rc = table->update_record(nullptr, &record); + if (rc != RC::SUCCESS) { + LOG_WARN("failed to delete record: %s", strrc(rc)); + return rc; + } + } + return RC::SUCCESS; +} + +RC UpdateOperator::next() +{ + return RC::RECORD_EOF; +} + +RC UpdateOperator::close() +{ + children_[0]->close(); + return RC::SUCCESS; +} diff --git a/src/observer/sql/operator/update_operator.h b/src/observer/sql/operator/update_operator.h new file mode 100644 index 000000000..5bc630d4b --- /dev/null +++ b/src/observer/sql/operator/update_operator.h @@ -0,0 +1,42 @@ +/* Copyright (c) 2021 Xie Meiyi(xiemeiyi@hust.edu.cn) and OceanBase and/or its affiliates. All rights reserved. +miniob is licensed under Mulan PSL v2. +You can use this software according to the terms and conditions of the Mulan PSL v2. +You may obtain a copy of Mulan PSL v2 at: + http://license.coscl.org.cn/MulanPSL2 +THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +See the Mulan PSL v2 for more details. */ + +// +// Created by wuxiaobai24 on 2022/10/6. +// + +#pragma once + +#include "sql/operator/operator.h" +#include "rc.h" + +class UpdateStmt; + +class UpdateOperator : public Operator +{ +public: + UpdateOperator(UpdateStmt *update_stmt) + : update_stmt_(update_stmt) + {} + + ~UpdateOperator() = default; + + RC open() override; + RC next() override; + RC close() override; + + Tuple * current_tuple() override { + return nullptr; + } + //int tuple_cell_num() const override + //RC tuple_cell_spec_at(int index, TupleCellSpec &spec) const override +private: + UpdateStmt *update_stmt_ = nullptr; +}; From dfdede3495d0c3327a23410577a290f53b901f26 Mon Sep 17 00:00:00 2001 From: wuxiaobai24 Date: Sat, 15 Oct 2022 17:25:53 +0800 Subject: [PATCH 3/3] fix update --- src/observer/sql/operator/update_operator.cpp | 5 ++-- src/observer/sql/stmt/update_stmt.cpp | 7 +++-- src/observer/sql/stmt/update_stmt.h | 7 +++-- src/observer/storage/common/table.cpp | 29 ++++++++++++++++++- src/observer/storage/common/table.h | 2 +- 5 files changed, 40 insertions(+), 10 deletions(-) diff --git a/src/observer/sql/operator/update_operator.cpp b/src/observer/sql/operator/update_operator.cpp index 0746ca4cb..f61034d31 100644 --- a/src/observer/sql/operator/update_operator.cpp +++ b/src/observer/sql/operator/update_operator.cpp @@ -42,8 +42,9 @@ RC UpdateOperator::open() RowTuple *row_tuple = static_cast(tuple); Record &record = row_tuple->record(); - - rc = table->update_record(nullptr, &record); + auto attr_name = update_stmt_->attribute_name(); + auto value = update_stmt_->values(); + rc = table->update_record(nullptr, &record, attr_name, value); if (rc != RC::SUCCESS) { LOG_WARN("failed to delete record: %s", strrc(rc)); return rc; diff --git a/src/observer/sql/stmt/update_stmt.cpp b/src/observer/sql/stmt/update_stmt.cpp index aff9d2747..313566b55 100644 --- a/src/observer/sql/stmt/update_stmt.cpp +++ b/src/observer/sql/stmt/update_stmt.cpp @@ -18,8 +18,8 @@ See the Mulan PSL v2 for more details. */ #include "storage/common/db.h" #include "storage/common/table.h" -UpdateStmt::UpdateStmt(Table *table, Value *values, int value_amount, FilterStmt *filter_stmt) - : table_ (table), values_(values), value_amount_(value_amount), filter_stmt_(filter_stmt) +UpdateStmt::UpdateStmt(Table *table, char *attribute_name, Value *values, FilterStmt *filter_stmt) + : table_(table), attribute_name_(attribute_name), values_(values), filter_stmt_(filter_stmt) {} UpdateStmt::~UpdateStmt() @@ -71,7 +71,8 @@ RC UpdateStmt::create(Db *db, const Updates &update_sql, Stmt *&stmt) return rc; } Value *values = const_cast(&update_sql.value); - stmt = new UpdateStmt(table, values, 1, filter_stmt); + char *attribute_name = update_sql.attribute_name; + stmt = new UpdateStmt(table, attribute_name, values, filter_stmt); return RC::SUCCESS; } diff --git a/src/observer/sql/stmt/update_stmt.h b/src/observer/sql/stmt/update_stmt.h index 25b9626dd..4a71bf6fb 100644 --- a/src/observer/sql/stmt/update_stmt.h +++ b/src/observer/sql/stmt/update_stmt.h @@ -25,7 +25,7 @@ class UpdateStmt : public Stmt public: UpdateStmt() = default; - UpdateStmt(Table *table, Value *values, int value_amount, FilterStmt *filter_stmt); + UpdateStmt(Table *table, char *attribute_name, Value *values, FilterStmt *filter_stmt); ~UpdateStmt() override; StmtType type() const override { return StmtType::UPDATE; } @@ -35,14 +35,15 @@ class UpdateStmt : public Stmt public: Table *table() const {return table_;} Value *values() const { return values_; } - int value_amount() const { return value_amount_; } + char *attribute_name() const { return attribute_name_; } FilterStmt *filter_stmt() const { return filter_stmt_; } private: Table *table_ = nullptr; Value *values_ = nullptr; - int value_amount_ = 0; + char* attribute_name_ = nullptr; + [[maybe_unused]]int value_amount_ = 1; FilterStmt *filter_stmt_ = nullptr; }; diff --git a/src/observer/storage/common/table.cpp b/src/observer/storage/common/table.cpp index 69ac7c5c7..8e9bfd298 100644 --- a/src/observer/storage/common/table.cpp +++ b/src/observer/storage/common/table.cpp @@ -731,8 +731,35 @@ RC Table::delete_record(Trx *trx, Record *record) return rc; } -RC Table::update_record(Trx *trx, Record *record) +RC Table::update_record(Trx *trx, Record *record, const char *attribute_name, const Value *value) { + // Update the record + const int normal_field_start_index = table_meta_.sys_field_num(); + for (int i = normal_field_start_index; i < table_meta_.field_num(); i++) { + const FieldMeta *field = table_meta_.field(i); + if (0 != strcmp(field->name(), attribute_name)) { + continue; + } + + if (field->type() != value->type) { + LOG_ERROR("Invalid value type. table name =%s, field name=%s, type=%d, but given=%d", + table_meta_.name(), + field->name(), + field->type(), + value->type); + return RC::SCHEMA_FIELD_TYPE_MISMATCH; + } + + size_t copy_len = field->len(); + if (field->type() == CHARS) { + const size_t data_len = strlen((const char *)value->data); + if (copy_len > data_len) { + copy_len = data_len + 1; + } + } + memcpy(record->data() + field->offset(), value->data, copy_len); + break; + } RC rc = RC::SUCCESS; if (trx != nullptr) { // TODO: trx support update record diff --git a/src/observer/storage/common/table.h b/src/observer/storage/common/table.h index fd875271a..0d4769f36 100644 --- a/src/observer/storage/common/table.h +++ b/src/observer/storage/common/table.h @@ -56,7 +56,7 @@ class Table { RC update_record(Trx *trx, const char *attribute_name, const Value *value, int condition_num, const Condition conditions[], int *updated_count); RC update_record(Trx *trx, Record *record); - RC update_record(Trx *trx, Record *record, const Value *value); + RC update_record(Trx *trx, Record *record, const char *attribute_name, const Value *value); RC delete_record(Trx *trx, ConditionFilter *filter, int *deleted_count); RC delete_record(Trx *trx, Record *record);