Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ GRTAGS
GPATH
GTAGS
.gitmodules
.cache
#*#
30 changes: 29 additions & 1 deletion src/observer/sql/executor/execute_stage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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();
Expand Down
1 change: 1 addition & 0 deletions src/observer/sql/executor/execute_stage.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
65 changes: 65 additions & 0 deletions src/observer/sql/operator/update_operator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/* 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<RowTuple *>(tuple);
Record &record = row_tuple->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;
}
}
return RC::SUCCESS;
}

RC UpdateOperator::next()
{
return RC::RECORD_EOF;
}

RC UpdateOperator::close()
{
children_[0]->close();
return RC::SUCCESS;
}
42 changes: 42 additions & 0 deletions src/observer/sql/operator/update_operator.h
Original file line number Diff line number Diff line change
@@ -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;
};
5 changes: 5 additions & 0 deletions src/observer/sql/stmt/stmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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");
}
Expand Down
64 changes: 58 additions & 6 deletions src/observer/sql/stmt/update_stmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,67 @@ 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, char *attribute_name, Value *values, FilterStmt *filter_stmt)
: table_(table), attribute_name_(attribute_name), values_(values), 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<std::string, Table *> table_map;
table_map.insert(std::pair<std::string, Table *>(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<Value*>(&update_sql.value);
char *attribute_name = update_sql.attribute_name;
stmt = new UpdateStmt(table, attribute_name, values, filter_stmt);

return RC::SUCCESS;
}
13 changes: 10 additions & 3 deletions src/observer/sql/stmt/update_stmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,32 @@ 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, char *attribute_name, Value *values, FilterStmt *filter_stmt);
~UpdateStmt() override;

StmtType type() const override { return StmtType::UPDATE; }
public:
static RC create(Db *db, const Updates &update_sql, Stmt *&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;
};

39 changes: 39 additions & 0 deletions src/observer/storage/common/table.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,45 @@ RC Table::delete_record(Trx *trx, Record *record)
return rc;
}

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
} 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;
Expand Down
2 changes: 2 additions & 0 deletions src/observer/storage/common/table.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 char *attribute_name, const Value *value);
RC delete_record(Trx *trx, ConditionFilter *filter, int *deleted_count);
RC delete_record(Trx *trx, Record *record);

Expand Down