未验证 提交 9f8437fe 编写于 作者: 羽飞's avatar 羽飞 提交者: GitHub

Merge pull request #42 from hnwyllmm/stmt

implement some operators
./deps/libevent/*
./deps/googletest/*
./deps/jsoncpp/*
./deps/libevent
./deps/googletest
./deps/jsoncpp
build/*
cmake-build-*/*
.vscode/*
......@@ -12,3 +12,7 @@ compile_commands.json
./vcs.xml
./workspace.xml
./modules.xml
GRTAGS
GPATH
GTAGS
#*#
......@@ -29,17 +29,20 @@ RUN wget http://yum-test.obvos.alibaba-inc.com/oceanbase/development-kit/el/7/x8
RUN git clone https://github.com/libevent/libevent -b release-2.1.12-stable \
&& mkdir -p ${HOME_DIR}/deps/libevent/build \
&& cmake -DEVENT__DISABLE_OPENSSL=ON -B ${HOME_DIR}/deps/libevent/build ${HOME_DIR}/deps/libevent && make -C ${HOME_DIR}/deps/libevent/build -j install \
&& cmake -DEVENT__DISABLE_OPENSSL=ON -B ${HOME_DIR}/deps/libevent/build ${HOME_DIR}/deps/libevent \
&& make -C ${HOME_DIR}/deps/libevent/build -j install \
&& rm -rf ${HOME_DIR}/deps/*
RUN git clone https://github.com/open-source-parsers/jsoncpp.git \
&& mkdir -p ${HOME_DIR}/deps/jsoncpp/build \
&& cmake -DJSONCPP_WITH_TESTS=OFF -DJSONCPP_WITH_POST_BUILD_UNITTEST=OFF -B ${HOME_DIR}/deps/jsoncpp/build ${HOME_DIR}/deps/jsoncpp/ && make -C ${HOME_DIR}/deps/jsoncpp/build -j install \
&& cmake -DJSONCPP_WITH_TESTS=OFF -DJSONCPP_WITH_POST_BUILD_UNITTEST=OFF -B ${HOME_DIR}/deps/jsoncpp/build ${HOME_DIR}/deps/jsoncpp/ \
&& make -C ${HOME_DIR}/deps/jsoncpp/build -j install \
&& rm -rf ${HOME_DIR}/deps/*
RUN git clone https://github.com/google/googletest \
&& mkdir -p ${HOME_DIR}/deps/googletest/build \
&& cmake -B ${HOME_DIR}/deps/googletest/build ${HOME_DIR}/deps/googletest && make -C ${HOME_DIR}/deps/googletest/build -j install \
&& cmake -B ${HOME_DIR}/deps/googletest/build ${HOME_DIR}/deps/googletest \
&& make -C ${HOME_DIR}/deps/googletest/build -j install \
&& rm -rf ${HOME_DIR}/deps/*
RUN wget http://ftp.gnu.org/gnu/bison/bison-3.7.tar.gz \
......
/* 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 Wangyunlai on 2022/07/08.
//
#pragma once
#include <functional>
namespace common {
class DeferHelper
{
public:
DeferHelper(const std::function<void()> &defer) : defer_(defer)
{}
~DeferHelper()
{
defer_();
}
private:
const std::function<void()> &defer_;
};
} // namespace common
#define DEFER(callback) common::DeferHelper defer_helper_##__LINE__(callback)
googletest @ b1f84bf1
Subproject commit b1f84bf1763b1010597bff13c79b5388eebdf205
jsoncpp @ 42e892d9
Subproject commit 42e892d96e47b1f6e29844cc705e148ec4856448
libevent @ 5df3037d
Subproject commit 5df3037d10556bfcb675bc73e516978b75fc7bc7
......@@ -57,21 +57,22 @@ count=3
[SessionStage]
ThreadId=SQLThreads
NextStages=ResolveStage
NextStages=PlanCacheStage
[ResolveStage]
[PlanCacheStage]
ThreadId=SQLThreads
NextStages=QueryCacheStage
#NextStages=OptimizeStage
NextStages=ParseStage
[QueryCacheStage]
[ParseStage]
ThreadId=SQLThreads
NextStages=PlanCacheStage
NextStages=ResolveStage
[PlanCacheStage]
[ResolveStage]
ThreadId=SQLThreads
NextStages=ExecuteStage,ParseStage
NextStages=QueryCacheStage
[ParseStage]
[QueryCacheStage]
ThreadId=SQLThreads
NextStages=OptimizeStage
......
......@@ -7,3 +7,12 @@ 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 Wangyunlai on 2022/6/23.
//
#pragma once
using PageNum = int32_t;
using SlotNum = int32_t;
......@@ -9,35 +9,34 @@ MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */
//
// Created by Wangyunlai on 2021/5/11.
// Created by Wangyunlai on 2022/6/7.
//
#ifndef __OBSERVER_EVENT_EXECUTION_PLAN_EVENT_H__
#define __OBSERVER_EVENT_EXECUTION_PLAN_EVENT_H__
#pragma once
#include "common/seda/stage_event.h"
#include "sql/parser/parse.h"
class SQLStageEvent;
class Stmt;
class ExecutionPlanEvent : public common::StageEvent {
class OptimizeEvent : public common::StageEvent {
public:
ExecutionPlanEvent(SQLStageEvent *sql_event, Query *sqls);
virtual ~ExecutionPlanEvent();
OptimizeEvent(SQLStageEvent *sql_event, common::StageEvent *parent_event)
: sql_event_(sql_event), parent_event_(parent_event)
{}
Query *sqls() const
{
return sqls_;
}
virtual ~OptimizeEvent() noexcept = default;
SQLStageEvent *sql_event() const
{
SQLStageEvent *sql_event() const {
return sql_event_;
}
common::StageEvent *parent_event() const {
return parent_event_;
}
private:
SQLStageEvent *sql_event_;
Query *sqls_;
SQLStageEvent *sql_event_ = nullptr;
common::StageEvent *parent_event_ = nullptr;
};
#endif // __OBSERVER_EVENT_EXECUTION_PLAN_EVENT_H__
\ No newline at end of file
......@@ -15,16 +15,23 @@ See the Mulan PSL v2 for more details. */
#include "session_event.h"
SessionEvent::SessionEvent(ConnectionContext *client) : client_(client)
{}
{
}
SessionEvent::~SessionEvent()
{}
{
}
ConnectionContext *SessionEvent::get_client() const
{
return client_;
}
Session *SessionEvent::session() const
{
return client_->session;
}
const char *SessionEvent::get_response() const
{
return response_.c_str();
......@@ -58,4 +65,4 @@ char *SessionEvent::get_request_buf()
int SessionEvent::get_request_buf_len()
{
return SOCKET_BUFFER_SIZE;
}
\ No newline at end of file
}
......@@ -21,12 +21,15 @@ See the Mulan PSL v2 for more details. */
#include "common/seda/stage_event.h"
#include "net/connection_context.h"
class Session;
class SessionEvent : public common::StageEvent {
public:
SessionEvent(ConnectionContext *client);
virtual ~SessionEvent();
ConnectionContext *get_client() const;
Session *session() const;
const char *get_response() const;
void set_response(const char *response);
......
......@@ -15,7 +15,7 @@ See the Mulan PSL v2 for more details. */
#include "event/sql_event.h"
#include "event/session_event.h"
SQLStageEvent::SQLStageEvent(SessionEvent *event, std::string &sql) : session_event_(event), sql_(sql)
SQLStageEvent::SQLStageEvent(SessionEvent *event, const std::string &sql) : session_event_(event), sql_(sql)
{}
SQLStageEvent::~SQLStageEvent() noexcept
......@@ -26,4 +26,4 @@ SQLStageEvent::~SQLStageEvent() noexcept
// session_event_ = nullptr;
// session_event->doneImmediate();
}
}
\ No newline at end of file
}
......@@ -15,30 +15,37 @@ See the Mulan PSL v2 for more details. */
#ifndef __OBSERVER_SQL_EVENT_SQLEVENT_H__
#define __OBSERVER_SQL_EVENT_SQLEVENT_H__
#include "common/seda/stage_event.h"
#include <string>
#include "common/seda/stage_event.h"
class SessionEvent;
class Stmt;
struct Query;
class SQLStageEvent : public common::StageEvent {
class SQLStageEvent : public common::StageEvent
{
public:
SQLStageEvent(SessionEvent *event, std::string &sql);
SQLStageEvent(SessionEvent *event, const std::string &sql);
virtual ~SQLStageEvent() noexcept;
const std::string &get_sql() const
{
return sql_;
}
SessionEvent *session_event() const
{
return session_event_;
}
const std::string &sql() const { return sql_; }
Query *query() const { return query_; }
Stmt *stmt() const { return stmt_; }
void set_sql(const char *sql) { sql_ = sql; }
void set_query(Query *query) { query_ = query; }
void set_stmt(Stmt *stmt) { stmt_ = stmt; }
private:
SessionEvent *session_event_;
std::string &sql_;
// void *context_;
SessionEvent *session_event_ = nullptr;
std::string sql_;
Query *query_ = nullptr;
Stmt *stmt_ = nullptr;
};
#endif //__SRC_OBSERVER_SQL_EVENT_SQLEVENT_H__
......@@ -17,20 +17,22 @@ See the Mulan PSL v2 for more details. */
#include "common/seda/stage_event.h"
class ExecutionPlanEvent;
class SQLStageEvent;
class StorageEvent : public common::StageEvent {
public:
StorageEvent(ExecutionPlanEvent *exe_event);
StorageEvent(SQLStageEvent *sql_event) : sql_event_(sql_event)
{}
virtual ~StorageEvent();
ExecutionPlanEvent *exe_event() const
SQLStageEvent *sql_event() const
{
return exe_event_;
return sql_event_;
}
private:
ExecutionPlanEvent *exe_event_;
SQLStageEvent *sql_event_;
};
#endif //__OBSERVER_SQL_EVENT_STORAGEEVENT_H__
......@@ -24,6 +24,7 @@ const char *strrc(RC rc)
RC_CASE_STRING(SUCCESS);
RC_CASE_STRING(GENERIC_ERROR);
RC_CASE_STRING(INVALID_ARGUMENT);
RC_CASE_STRING(UNIMPLENMENT);
RC_CASE_STRING(SQL_SYNTAX);
RC_CASE_STRING(BUFFERPOOL);
RC_CASE_STRING(RECORD);
......@@ -179,4 +180,4 @@ const char *strrc(RC rc)
return "UNKNOWN";
}
}
}
\ No newline at end of file
}
......@@ -172,10 +172,11 @@ enum RC {
/* beginning-of-error-codes */
GENERIC_ERROR, /* Generic error */
INVALID_ARGUMENT, /* Invalid argument */
UNIMPLENMENT, /* not implenment yet */
SQL_SYNTAX, /* SQL Syntax error */
BUFFERPOOL, /* Buffer pool error*/
RECORD, /* Record error */
INTERNAL, /* Internal logic error in SQLite */
INTERNAL, /* Internal logic error in SQL */
PERM, /* Access permission denied */
ABORT, /* Callback routine requested an abort */
BUSY, /* The database file is locked */
......
......@@ -14,6 +14,8 @@ See the Mulan PSL v2 for more details. */
#include "session/session.h"
#include "storage/trx/trx.h"
#include "storage/common/db.h"
#include "storage/default/default_handler.h"
Session &Session::default_session()
{
......@@ -21,7 +23,7 @@ Session &Session::default_session()
return session;
}
Session::Session(const Session &other) : current_db_(other.current_db_)
Session::Session(const Session &other) : db_(other.db_)
{}
Session::~Session()
......@@ -30,13 +32,30 @@ Session::~Session()
trx_ = nullptr;
}
const std::string &Session::get_current_db() const
const char *Session::get_current_db_name() const
{
return current_db_;
if (db_ != nullptr)
return db_->name();
else
return "";
}
Db *Session::get_current_db() const
{
return db_;
}
void Session::set_current_db(const std::string &dbname)
{
current_db_ = dbname;
DefaultHandler &handler = DefaultHandler::get_default();
Db *db = handler.find_db(dbname.c_str());
if (db == nullptr) {
LOG_WARN("no such database: %s", dbname.c_str());
return;
}
LOG_TRACE("change db to %s", dbname.c_str());
db_ = db;
}
void Session::set_trx_multi_operation_mode(bool multi_operation_mode)
......
......@@ -12,12 +12,12 @@ See the Mulan PSL v2 for more details. */
// Created by Wangyunlai on 2021/5/12.
//
#ifndef __OBSERVER_SESSION_SESSION_H__
#define __OBSERVER_SESSION_SESSION_H__
#pragma once
#include <string>
class Trx;
class Db;
class Session {
public:
......@@ -31,7 +31,9 @@ public:
Session(const Session &other);
void operator=(Session &) = delete;
const std::string &get_current_db() const;
const char *get_current_db_name() const;
Db *get_current_db() const;
void set_current_db(const std::string &dbname);
void set_trx_multi_operation_mode(bool multi_operation_mode);
......@@ -40,9 +42,7 @@ public:
Trx *current_trx();
private:
std::string current_db_;
Db *db_ = nullptr;
Trx *trx_ = nullptr;
bool trx_multi_operation_mode_ = false; // 当前事务的模式,是否多语句模式. 单语句模式自动提交
};
#endif // __OBSERVER_SESSION_SESSION_H__
\ No newline at end of file
......@@ -34,7 +34,7 @@ using namespace common;
const std::string SessionStage::SQL_METRIC_TAG = "SessionStage.sql";
// Constructor
SessionStage::SessionStage(const char *tag) : Stage(tag), resolve_stage_(nullptr), sql_metric_(nullptr)
SessionStage::SessionStage(const char *tag) : Stage(tag), plan_cache_stage_(nullptr), sql_metric_(nullptr)
{}
// Destructor
......@@ -73,7 +73,7 @@ bool SessionStage::initialize()
LOG_TRACE("Enter");
std::list<Stage *>::iterator stgp = next_stage_list_.begin();
resolve_stage_ = *(stgp++);
plan_cache_stage_ = *(stgp++);
MetricsRegistry &metricsRegistry = get_metrics_registry();
sql_metric_ = new SimpleTimer();
......@@ -138,7 +138,6 @@ void SessionStage::callback_event(StageEvent *event, CallbackContext *context)
void SessionStage::handle_request(StageEvent *event)
{
SessionEvent *sev = dynamic_cast<SessionEvent *>(event);
if (nullptr == sev) {
LOG_ERROR("Cannot cat event to sessionEvent");
......@@ -169,5 +168,5 @@ void SessionStage::handle_request(StageEvent *event)
sev->push_callback(cb);
SQLStageEvent *sql_event = new SQLStageEvent(sev, sql);
resolve_stage_->handle_event(sql_event);
plan_cache_stage_->handle_event(sql_event);
}
......@@ -47,8 +47,8 @@ protected:
void handle_request(common::StageEvent *event);
private:
Stage *resolve_stage_;
common::SimpleTimer *sql_metric_;
Stage *plan_cache_stage_ = nullptr;
common::SimpleTimer *sql_metric_ = nullptr;
static const std::string SQL_METRIC_TAG;
};
......
......@@ -19,7 +19,9 @@ See the Mulan PSL v2 for more details. */
#include "sql/parser/parse.h"
#include "rc.h"
class SQLStageEvent;
class SessionEvent;
class SelectStmt;
class ExecuteStage : public common::Stage {
public:
......@@ -37,7 +39,14 @@ protected:
void callback_event(common::StageEvent *event, common::CallbackContext *context) override;
void handle_request(common::StageEvent *event);
RC do_select(const char *db, Query *sql, SessionEvent *session_event);
RC do_help(SQLStageEvent *session_event);
RC do_create_table(SQLStageEvent *sql_event);
RC do_create_index(SQLStageEvent *sql_event);
RC do_show_tables(SQLStageEvent *sql_event);
RC do_desc_table(SQLStageEvent *sql_event);
RC do_select(SQLStageEvent *sql_event);
RC do_insert(SQLStageEvent *sql_event);
RC do_delete(SQLStageEvent *sql_event);
protected:
private:
......
/* 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 Meiyi & Wangyunlai on 2021/5/14.
//
#include "sql/executor/tuple.h"
#include "storage/common/table.h"
#include "common/log/log.h"
Tuple::Tuple(const Tuple &other)
{
LOG_PANIC("Copy constructor of tuple is not supported");
exit(1);
}
Tuple::Tuple(Tuple &&other) noexcept : values_(std::move(other.values_))
{}
Tuple &Tuple::operator=(Tuple &&other) noexcept
{
if (&other == this) {
return *this;
}
values_.clear();
values_.swap(other.values_);
return *this;
}
Tuple::~Tuple()
{}
// add (Value && value)
void Tuple::add(TupleValue *value)
{
values_.emplace_back(value);
}
void Tuple::add(const std::shared_ptr<TupleValue> &other)
{
values_.emplace_back(other);
}
void Tuple::add(int value)
{
add(new IntValue(value));
}
void Tuple::add(float value)
{
add(new FloatValue(value));
}
void Tuple::add(const char *s, int len)
{
add(new StringValue(s, len));
}
////////////////////////////////////////////////////////////////////////////////
std::string TupleField::to_string() const
{
return std::string(table_name_) + "." + field_name_ + std::to_string(type_);
}
////////////////////////////////////////////////////////////////////////////////
void TupleSchema::from_table(const Table *table, TupleSchema &schema)
{
const char *table_name = table->name();
const TableMeta &table_meta = table->table_meta();
const int field_num = table_meta.field_num();
for (int i = 0; i < field_num; i++) {
const FieldMeta *field_meta = table_meta.field(i);
if (field_meta->visible()) {
schema.add(field_meta->type(), table_name, field_meta->name());
}
}
}
void TupleSchema::add(AttrType type, const char *table_name, const char *field_name)
{
fields_.emplace_back(type, table_name, field_name);
}
void TupleSchema::add_if_not_exists(AttrType type, const char *table_name, const char *field_name)
{
for (const auto &field : fields_) {
if (0 == strcmp(field.table_name(), table_name) && 0 == strcmp(field.field_name(), field_name)) {
return;
}
}
add(type, table_name, field_name);
}
void TupleSchema::append(const TupleSchema &other)
{
fields_.reserve(fields_.size() + other.fields_.size());
for (const auto &field : other.fields_) {
fields_.emplace_back(field);
}
}
int TupleSchema::index_of_field(const char *table_name, const char *field_name) const
{
const int size = fields_.size();
for (int i = 0; i < size; i++) {
const TupleField &field = fields_[i];
if (0 == strcmp(field.table_name(), table_name) && 0 == strcmp(field.field_name(), field_name)) {
return i;
}
}
return -1;
}
void TupleSchema::print(std::ostream &os) const
{
if (fields_.empty()) {
os << "No schema";
return;
}
// 判断有多张表还是只有一张表
std::set<std::string> table_names;
for (const auto &field : fields_) {
table_names.insert(field.table_name());
}
for (std::vector<TupleField>::const_iterator iter = fields_.begin(), end = --fields_.end(); iter != end; ++iter) {
if (table_names.size() > 1) {
os << iter->table_name() << ".";
}
os << iter->field_name() << " | ";
}
if (table_names.size() > 1) {
os << fields_.back().table_name() << ".";
}
os << fields_.back().field_name() << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
TupleSet::TupleSet(TupleSet &&other) : tuples_(std::move(other.tuples_)), schema_(other.schema_)
{
other.schema_.clear();
}
TupleSet &TupleSet::operator=(TupleSet &&other)
{
if (this == &other) {
return *this;
}
schema_.clear();
schema_.append(other.schema_);
other.schema_.clear();
tuples_.clear();
tuples_.swap(other.tuples_);
return *this;
}
void TupleSet::add(Tuple &&tuple)
{
tuples_.emplace_back(std::move(tuple));
}
void TupleSet::clear()
{
tuples_.clear();
schema_.clear();
}
void TupleSet::print(std::ostream &os) const
{
if (schema_.fields().empty()) {
LOG_WARN("Got empty schema");
return;
}
schema_.print(os);
for (const Tuple &item : tuples_) {
const std::vector<std::shared_ptr<TupleValue>> &values = item.values();
for (std::vector<std::shared_ptr<TupleValue>>::const_iterator iter = values.begin(), end = --values.end();
iter != end;
++iter) {
(*iter)->to_string(os);
os << " | ";
}
values.back()->to_string(os);
os << std::endl;
}
}
void TupleSet::set_schema(const TupleSchema &schema)
{
schema_ = schema;
}
const TupleSchema &TupleSet::get_schema() const
{
return schema_;
}
bool TupleSet::is_empty() const
{
return tuples_.empty();
}
int TupleSet::size() const
{
return tuples_.size();
}
const Tuple &TupleSet::get(int index) const
{
return tuples_[index];
}
const std::vector<Tuple> &TupleSet::tuples() const
{
return tuples_;
}
/////////////////////////////////////////////////////////////////////////////
TupleRecordConverter::TupleRecordConverter(Table *table, TupleSet &tuple_set) : table_(table), tuple_set_(tuple_set)
{}
void TupleRecordConverter::add_record(const char *record)
{
const TupleSchema &schema = tuple_set_.schema();
Tuple tuple;
const TableMeta &table_meta = table_->table_meta();
for (const TupleField &field : schema.fields()) {
const FieldMeta *field_meta = table_meta.field(field.field_name());
assert(field_meta != nullptr);
switch (field_meta->type()) {
case INTS: {
int value = *(int *)(record + field_meta->offset());
tuple.add(value);
} break;
case FLOATS: {
float value = *(float *)(record + field_meta->offset());
tuple.add(value);
} break;
case CHARS: {
const char *s = record + field_meta->offset(); // 现在当做Cstring来处理
tuple.add(s, strlen(s));
} break;
default: {
LOG_PANIC("Unsupported field type. type=%d", field_meta->type());
}
}
}
tuple_set_.add(std::move(tuple));
}
/* 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 Meiyi & Wangyunlai on 2021/5/14.
//
#ifndef __OBSERVER_SQL_EXECUTOR_TUPLE_H_
#define __OBSERVER_SQL_EXECUTOR_TUPLE_H_
#include <memory>
#include <vector>
#include "sql/parser/parse.h"
#include "sql/executor/value.h"
class Table;
class Tuple {
public:
Tuple() = default;
Tuple(const Tuple &other);
~Tuple();
Tuple(Tuple &&other) noexcept;
Tuple &operator=(Tuple &&other) noexcept;
void add(TupleValue *value);
void add(const std::shared_ptr<TupleValue> &other);
void add(int value);
void add(float value);
void add(const char *s, int len);
const std::vector<std::shared_ptr<TupleValue>> &values() const
{
return values_;
}
int size() const
{
return values_.size();
}
const TupleValue &get(int index) const
{
return *values_[index];
}
const std::shared_ptr<TupleValue> &get_pointer(int index) const
{
return values_[index];
}
private:
std::vector<std::shared_ptr<TupleValue>> values_;
};
class TupleField {
public:
TupleField(AttrType type, const char *table_name, const char *field_name)
: type_(type), table_name_(table_name), field_name_(field_name)
{}
AttrType type() const
{
return type_;
}
const char *table_name() const
{
return table_name_.c_str();
}
const char *field_name() const
{
return field_name_.c_str();
}
std::string to_string() const;
private:
AttrType type_;
std::string table_name_;
std::string field_name_;
};
class TupleSchema {
public:
TupleSchema() = default;
~TupleSchema() = default;
void add(AttrType type, const char *table_name, const char *field_name);
void add_if_not_exists(AttrType type, const char *table_name, const char *field_name);
// void merge(const TupleSchema &other);
void append(const TupleSchema &other);
const std::vector<TupleField> &fields() const
{
return fields_;
}
const TupleField &field(int index) const
{
return fields_[index];
}
int index_of_field(const char *table_name, const char *field_name) const;
void clear()
{
fields_.clear();
}
void print(std::ostream &os) const;
public:
static void from_table(const Table *table, TupleSchema &schema);
private:
std::vector<TupleField> fields_;
};
class TupleSet {
public:
TupleSet() = default;
TupleSet(TupleSet &&other);
explicit TupleSet(const TupleSchema &schema) : schema_(schema)
{}
TupleSet &operator=(TupleSet &&other);
~TupleSet() = default;
void set_schema(const TupleSchema &schema);
const TupleSchema &get_schema() const;
void add(Tuple &&tuple);
void clear();
bool is_empty() const;
int size() const;
const Tuple &get(int index) const;
const std::vector<Tuple> &tuples() const;
void print(std::ostream &os) const;
public:
const TupleSchema &schema() const
{
return schema_;
}
private:
std::vector<Tuple> tuples_;
TupleSchema schema_;
};
class TupleRecordConverter {
public:
TupleRecordConverter(Table *table, TupleSet &tuple_set);
void add_record(const char *record);
private:
Table *table_;
TupleSet &tuple_set_;
};
#endif //__OBSERVER_SQL_EXECUTOR_TUPLE_H_
/* 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 Meiyi & Wangyunlai on 2021/5/14.
//
#ifndef __OBSERVER_SQL_EXECUTOR_VALUE_H_
#define __OBSERVER_SQL_EXECUTOR_VALUE_H_
#include <string.h>
#include <string>
#include <ostream>
class TupleValue {
public:
TupleValue() = default;
virtual ~TupleValue() = default;
virtual void to_string(std::ostream &os) const = 0;
virtual int compare(const TupleValue &other) const = 0;
private:
};
class IntValue : public TupleValue {
public:
explicit IntValue(int value) : value_(value)
{}
void to_string(std::ostream &os) const override
{
os << value_;
}
int compare(const TupleValue &other) const override
{
const IntValue &int_other = (const IntValue &)other;
return value_ - int_other.value_;
}
private:
int value_;
};
class FloatValue : public TupleValue {
public:
explicit FloatValue(float value) : value_(value)
{}
void to_string(std::ostream &os) const override
{
os << value_;
}
int compare(const TupleValue &other) const override
{
const FloatValue &float_other = (const FloatValue &)other;
float result = value_ - float_other.value_;
if (result > 0) { // 浮点数没有考虑精度问题
return 1;
}
if (result < 0) {
return -1;
}
return 0;
}
private:
float value_;
};
class StringValue : public TupleValue {
public:
StringValue(const char *value, int len) : value_(value, len)
{}
explicit StringValue(const char *value) : value_(value)
{}
void to_string(std::ostream &os) const override
{
os << value_;
}
int compare(const TupleValue &other) const override
{
const StringValue &string_other = (const StringValue &)other;
return strcmp(value_.c_str(), string_other.value_.c_str());
}
private:
std::string value_;
};
#endif //__OBSERVER_SQL_EXECUTOR_VALUE_H_
......@@ -9,21 +9,18 @@ MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */
//
// Created by Wangyunlai on 2021/5/11.
// Created by Wangyunlai on 2022/07/05.
//
#include "event/execution_plan_event.h"
#include "event/sql_event.h"
#include "sql/expr/tuple.h"
ExecutionPlanEvent::ExecutionPlanEvent(SQLStageEvent *sql_event, Query *sqls) : sql_event_(sql_event), sqls_(sqls)
{}
ExecutionPlanEvent::~ExecutionPlanEvent()
RC FieldExpr::get_value(const Tuple &tuple, TupleCell &cell) const
{
sql_event_ = nullptr;
// if (sql_event_) {
// sql_event_->doneImmediate();
// }
return tuple.find_cell(field_, cell);
}
query_destroy(sqls_);
sqls_ = nullptr;
RC ValueExpr::get_value(const Tuple &tuple, TupleCell & cell) const
{
cell = tuple_cell_;
}
/* 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 Wangyunlai on 2022/07/05.
//
#pragma once
#include "storage/common/field.h"
#include "sql/expr/tuple_cell.h"
class Tuple;
enum class ExprType {
NONE,
FIELD,
VALUE,
};
class Expression
{
public:
Expression() = default;
virtual ~Expression() = default;
virtual RC get_value(const Tuple &tuple, TupleCell &cell) const = 0;
virtual ExprType type() const = 0;
};
class FieldExpr : public Expression
{
public:
FieldExpr() = default;
FieldExpr(const Table *table, const FieldMeta *field) : field_(table, field)
{}
virtual ~FieldExpr() = default;
ExprType type() const override
{
return ExprType::FIELD;
}
Field &field()
{
return field_;
}
const Field &field() const
{
return field_;
}
const char *table_name() const
{
return field_.table_name();
}
const char *field_name() const
{
return field_.field_name();
}
RC get_value(const Tuple &tuple, TupleCell &cell) const override;
private:
Field field_;
};
class ValueExpr : public Expression
{
public:
ValueExpr() = default;
ValueExpr(const Value &value) : tuple_cell_(value.type, (char *)value.data)
{}
virtual ~ValueExpr() = default;
RC get_value(const Tuple &tuple, TupleCell & cell) const override;
ExprType type() const override
{
return ExprType::VALUE;
}
void get_tuple_cell(TupleCell &cell) const {
cell = tuple_cell_;
}
private:
TupleCell tuple_cell_;
};
/* 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 Wangyunlai on 2021/5/14.
//
#pragma once
#include <memory>
#include <vector>
#include "common/log/log.h"
#include "sql/parser/parse.h"
#include "sql/expr/tuple_cell.h"
#include "sql/expr/expression.h"
#include "storage/common/record.h"
class Table;
class TupleCellSpec
{
public:
TupleCellSpec() = default;
TupleCellSpec(Expression *expr) : expression_(expr)
{}
~TupleCellSpec()
{
if (expression_) {
delete expression_;
expression_ = nullptr;
}
}
void set_alias(const char *alias)
{
this->alias_ = alias;
}
const char *alias() const
{
return alias_;
}
Expression *expression() const
{
return expression_;
}
private:
const char *alias_ = nullptr;
Expression *expression_ = nullptr;
};
class Tuple
{
public:
Tuple() = default;
virtual ~Tuple() = default;
virtual int cell_num() const = 0;
virtual RC cell_at(int index, TupleCell &cell) const = 0;
virtual RC find_cell(const Field &field, TupleCell &cell) const = 0;
virtual RC cell_spec_at(int index, const TupleCellSpec *&spec) const = 0;
};
class RowTuple : public Tuple
{
public:
RowTuple() = default;
virtual ~RowTuple()
{
for (TupleCellSpec *spec : speces_) {
delete spec;
}
speces_.clear();
}
void set_record(Record *record)
{
this->record_ = record;
}
void set_schema(const Table *table, const std::vector<FieldMeta> *fields)
{
table_ = table;
this->speces_.reserve(fields->size());
for (const FieldMeta &field : *fields) {
speces_.push_back(new TupleCellSpec(new FieldExpr(table, &field)));
}
}
int cell_num() const override
{
return speces_.size();
}
RC cell_at(int index, TupleCell &cell) const override
{
if (index < 0 || index >= speces_.size()) {
LOG_WARN("invalid argument. index=%d", index);
return RC::INVALID_ARGUMENT;
}
const TupleCellSpec *spec = speces_[index];
FieldExpr *field_expr = (FieldExpr *)spec->expression();
const FieldMeta *field_meta = field_expr->field().meta();
cell.set_type(field_meta->type());
cell.set_data(this->record_->data() + field_meta->offset());
return RC::SUCCESS;
}
RC find_cell(const Field &field, TupleCell &cell) const override
{
const char *table_name = field.table_name();
if (0 != strcmp(table_name, table_->name())) {
return RC::NOTFOUND;
}
const char *field_name = field.field_name();
for (int i = 0; i < speces_.size(); ++i) {
const FieldExpr * field_expr = (const FieldExpr *)speces_[i]->expression();
const Field &field = field_expr->field();
if (0 == strcmp(field_name, field.field_name())) {
return cell_at(i, cell);
}
}
return RC::NOTFOUND;
}
RC cell_spec_at(int index, const TupleCellSpec *&spec) const override
{
if (index < 0 || index >= speces_.size()) {
LOG_WARN("invalid argument. index=%d", index);
return RC::INVALID_ARGUMENT;
}
spec = speces_[index];
return RC::SUCCESS;
}
Record &record()
{
return *record_;
}
const Record &record() const
{
return *record_;
}
private:
Record *record_ = nullptr;
const Table *table_ = nullptr;
std::vector<TupleCellSpec *> speces_;
};
/*
class CompositeTuple : public Tuple
{
public:
int cell_num() const override;
RC cell_at(int index, TupleCell &cell) const = 0;
private:
int cell_num_ = 0;
std::vector<Tuple *> tuples_;
};
*/
class ProjectTuple : public Tuple
{
public:
ProjectTuple() = default;
virtual ~ProjectTuple()
{
for (TupleCellSpec *spec : speces_) {
delete spec;
}
speces_.clear();
}
void set_tuple(Tuple *tuple)
{
this->tuple_ = tuple;
}
void add_cell_spec(TupleCellSpec *spec)
{
speces_.push_back(spec);
}
int cell_num() const override
{
return speces_.size();
}
RC cell_at(int index, TupleCell &cell) const override
{
if (index < 0 || index >= speces_.size()) {
return RC::GENERIC_ERROR;
}
if (tuple_ == nullptr) {
return RC::GENERIC_ERROR;
}
const TupleCellSpec *spec = speces_[index];
return spec->expression()->get_value(*tuple_, cell);
}
RC find_cell(const Field &field, TupleCell &cell) const override
{
return tuple_->find_cell(field, cell);
}
RC cell_spec_at(int index, const TupleCellSpec *&spec) const override
{
if (index < 0 || index >= speces_.size()) {
return RC::NOTFOUND;
}
spec = speces_[index];
return RC::SUCCESS;
}
private:
std::vector<TupleCellSpec *> speces_;
Tuple *tuple_ = nullptr;
};
/* 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 WangYunlai on 2022/07/05.
//
#include "sql/expr/tuple_cell.h"
#include "storage/common/field.h"
#include "common/log/log.h"
#include "util/comparator.h"
void TupleCell::to_string(std::ostream &os) const
{
switch (attr_type_) {
case INTS: {
os << *(int *)data_;
} break;
case FLOATS: {
os << *(float *)data_;
} break;
case CHARS: {
for (int i = 0; i < 4; i++) { // the max length of CHARS is 4
if (data_[i] == '\0') {
break;
}
os << data_[i];
}
} break;
default: {
LOG_WARN("unsupported attr type: %d", attr_type_);
} break;
}
}
int TupleCell::compare(const TupleCell &other) const
{
if (this->attr_type_ == other.attr_type_) {
switch (this->attr_type_) {
case INTS: return compare_int(this->data_, other.data_);
case FLOATS: return compare_float(this->data_, other.data_);
case CHARS: return compare_string(this->data_, other.data_, 4);
default: {
LOG_WARN("unsupported type: %d", this->attr_type_);
}
}
} else if (this->attr_type_ == INTS && other.attr_type_ == FLOATS) {
float this_data = *(int *)data_;
return compare_float(&this_data, other.data_);
} else if (this->attr_type_ == FLOATS && other.attr_type_ == INTS) {
float other_data = *(int *)other.data_;
return compare_float(data_, &other_data);
}
LOG_WARN("not supported");
return -1; // TODO return rc?
}
/* 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 WangYunlai on 2022/6/7.
//
#pragma once
#include <iostream>
#include "storage/common/table.h"
#include "storage/common/field_meta.h"
class TupleCell
{
public:
TupleCell() = default;
TupleCell(FieldMeta *meta, char *data)
: TupleCell(meta->type(), data)
{}
TupleCell(AttrType attr_type, char *data)
: attr_type_(attr_type), data_(data)
{}
void set_type(AttrType type) { this->attr_type_ = type; }
void set_data(char *data) { this->data_ = data; }
void set_data(const char *data) { this->set_data(const_cast<char *>(data)); }
void to_string(std::ostream &os) const;
int compare(const TupleCell &other) const;
const char *data() const
{
return data_;
}
AttrType attr_type() const
{
return attr_type_;
}
private:
AttrType attr_type_ = UNDEFINED;
char *data_ = nullptr; // real data. no need to move to field_meta.offset
};
......@@ -9,46 +9,55 @@ MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */
//
// Created by Meiyi & Wangyunlai on 2021/5/14.
// Created by WangYunlai on 2022/6/27.
//
#include "sql/executor/execution_node.h"
#include "storage/common/table.h"
#include "common/log/log.h"
#include "sql/operator/delete_operator.h"
#include "storage/common/record.h"
#include "storage/common/table.h"
#include "sql/stmt/delete_stmt.h"
SelectExeNode::SelectExeNode() : table_(nullptr)
{}
SelectExeNode::~SelectExeNode()
RC DeleteOperator::open()
{
for (DefaultConditionFilter *&filter : condition_filters_) {
delete filter;
if (children_.size() != 1) {
LOG_WARN("delete operator must has 1 child");
return RC::INTERNAL;
}
condition_filters_.clear();
}
RC SelectExeNode::init(
Trx *trx, Table *table, TupleSchema &&tuple_schema, std::vector<DefaultConditionFilter *> &&condition_filters)
{
trx_ = trx;
table_ = table;
tuple_schema_ = tuple_schema;
condition_filters_ = std::move(condition_filters);
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 = delete_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();
rc = table->delete_record(nullptr, &record);
if (rc != RC::SUCCESS) {
LOG_WARN("failed to delete record: %s", strrc(rc));
return rc;
}
}
return RC::SUCCESS;
}
void record_reader(const char *data, void *context)
RC DeleteOperator::next()
{
TupleRecordConverter *converter = (TupleRecordConverter *)context;
converter->add_record(data);
return RC::RECORD_EOF;
}
RC SelectExeNode::execute(TupleSet &tuple_set)
RC DeleteOperator::close()
{
CompositeConditionFilter condition_filter;
condition_filter.init((const ConditionFilter **)condition_filters_.data(), condition_filters_.size());
tuple_set.clear();
tuple_set.set_schema(tuple_schema_);
TupleRecordConverter converter(table_, tuple_set);
return table_->scan_record(trx_, &condition_filter, -1, (void *)&converter, record_reader);
}
\ No newline at end of file
children_[0]->close();
return RC::SUCCESS;
}
/* 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 WangYunlai on 2022/6/9.
//
#pragma once
#include "sql/operator/operator.h"
#include "rc.h"
class DeleteStmt;
class DeleteOperator : public Operator
{
public:
DeleteOperator(DeleteStmt *delete_stmt)
: delete_stmt_(delete_stmt)
{}
virtual ~DeleteOperator() = 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:
DeleteStmt *delete_stmt_ = nullptr;
};
/* 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 Wangyunlai on 2022/07/08.
//
#include "sql/operator/index_scan_operator.h"
#include "storage/index/index.h"
IndexScanOperator::IndexScanOperator(const Table *table, Index *index,
const TupleCell *left_cell, bool left_inclusive,
const TupleCell *right_cell, bool right_inclusive)
: table_(table), index_(index),
left_inclusive_(left_inclusive), right_inclusive_(right_inclusive)
{
if (left_cell) {
left_cell_ = *left_cell;
}
if (right_cell) {
right_cell_ = *right_cell;
}
}
RC IndexScanOperator::open()
{
if (nullptr == table_ || nullptr == index_) {
return RC::INTERNAL;
}
IndexScanner *index_scanner = index_->create_scanner(left_cell_.data(), left_inclusive_,
right_cell_.data(), right_inclusive_);
if (nullptr == index_scanner) {
LOG_WARN("failed to create index scanner");
return RC::INTERNAL;
}
record_handler_ = table_->record_handler();
if (nullptr == record_handler_) {
LOG_WARN("invalid record handler");
index_scanner->destroy();
return RC::INTERNAL;
}
index_scanner_ = index_scanner;
tuple_.set_schema(table_, table_->table_meta().field_metas());
return RC::SUCCESS;
}
RC IndexScanOperator::next()
{
RID rid;
RC rc = index_scanner_->next_entry(&rid);
if (rc != RC::SUCCESS) {
return rc;
}
return record_handler_->get_record(&rid, &current_record_);
}
RC IndexScanOperator::close()
{
index_scanner_->destroy();
index_scanner_ = nullptr;
return RC::SUCCESS;
}
Tuple * IndexScanOperator::current_tuple()
{
tuple_.set_record(&current_record_);
return &tuple_;
}
/* 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 Wangyunlai on 2022/07/08.
//
#pragma once
#include "sql/operator/operator.h"
#include "sql/expr/tuple.h"
class IndexScanOperator : public Operator
{
public:
IndexScanOperator(const Table *table, Index *index,
const TupleCell *left_cell, bool left_inclusive,
const TupleCell *right_cell, bool right_inclusive);
virtual ~IndexScanOperator() = default;
RC open() override;
RC next() override;
RC close() override;
Tuple * current_tuple() override;
private:
const Table *table_ = nullptr;
Index *index_ = nullptr;
IndexScanner *index_scanner_ = nullptr;
RecordFileHandler *record_handler_ = nullptr;
Record current_record_;
RowTuple tuple_;
TupleCell left_cell_;
TupleCell right_cell_;
bool left_inclusive_;
bool right_inclusive_;
};
/* 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 WangYunlai on 2021/6/9.
//
#include "sql/operator/insert_operator.h"
#include "sql/stmt/insert_stmt.h"
#include "storage/common/table.h"
#include "rc.h"
RC InsertOperator::open()
{
Table *table = insert_stmt_->table();
const Value *values = insert_stmt_->values();
int value_amount = insert_stmt_->value_amount();
return table->insert_record(nullptr, value_amount, values); // TODO trx
}
RC InsertOperator::next()
{
return RC::RECORD_EOF;
}
RC InsertOperator::close()
{
return RC::SUCCESS;
}
/* 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 WangYunlai on 2021/6/7.
//
#pragma once
#include "sql/operator/operator.h"
#include "sql/parser/parse.h"
#include "rc.h"
class InsertStmt;
class InsertOperator : public Operator
{
public:
InsertOperator(InsertStmt *insert_stmt)
: insert_stmt_(insert_stmt)
{}
virtual ~InsertOperator() = default;
RC open() override;
RC next() override;
RC close() override;
private:
InsertStmt *insert_stmt_ = nullptr;
};
/* 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 WangYunlai on 2021/6/10.
//
#pragma once
#include "sql/parser/parse.h"
#include "sql/operator/operator.h"
#include "rc.h"
// TODO fixme
class JoinOperator : public Operator
{
public:
JoinOperator(Operator *left, Operator *right)
{}
virtual ~JoinOperator() = default;
RC open() override;
RC next() override;
RC close() override;
private:
Operator *left_ = nullptr;
Operator *right_ = nullptr;
bool round_done_ = true;
};
/* 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 WangYunlai on 2021/6/7.
//
#pragma once
#include <vector>
#include "rc.h"
#include "sql/expr/tuple.h"
class Record;
class TupleCellSpec;
class Operator
{
public:
Operator()
{}
virtual ~Operator() = default;
virtual RC open() = 0;
virtual RC next() = 0;
virtual RC close() = 0;
virtual Tuple * current_tuple() = 0;
//virtual int tuple_cell_num() const = 0;
//virtual RC tuple_cell_spec_at(int index, TupleCellSpec *&spec) const = 0;
void add_child(Operator *oper) {
children_.push_back(oper);
}
protected:
std::vector<Operator *> children_;
};
/* 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 WangYunlai on 2022/6/27.
//
#include "common/log/log.h"
#include "sql/operator/predicate_operator.h"
#include "storage/common/record.h"
#include "sql/stmt/filter_stmt.h"
#include "storage/common/field.h"
RC PredicateOperator::open()
{
if (children_.size() != 1) {
LOG_WARN("predicate operator must has one child");
return RC::INTERNAL;
}
return children_[0]->open();
}
RC PredicateOperator::next()
{
RC rc = RC::SUCCESS;
Operator *oper = children_[0];
while (RC::SUCCESS == (rc = oper->next())) {
Tuple *tuple = oper->current_tuple();
if (nullptr == tuple) {
rc = RC::INTERNAL;
LOG_WARN("failed to get tuple from operator");
break;
}
if (do_predicate(static_cast<RowTuple &>(*tuple))) {
return rc;
}
}
return rc;
}
RC PredicateOperator::close()
{
children_[0]->close();
return RC::SUCCESS;
}
Tuple * PredicateOperator::current_tuple()
{
return children_[0]->current_tuple();
}
bool PredicateOperator::do_predicate(RowTuple &tuple)
{
if (filter_stmt_ == nullptr || filter_stmt_->filter_units().empty()) {
return true;
}
for (const FilterUnit *filter_unit : filter_stmt_->filter_units()) {
Expression *left_expr = filter_unit->left();
Expression *right_expr = filter_unit->right();
CompOp comp = filter_unit->comp();
TupleCell left_cell;
TupleCell right_cell;
left_expr->get_value(tuple, left_cell);
right_expr->get_value(tuple, right_cell);
const int compare = left_cell.compare(right_cell);
bool filter_result = false;
switch (comp) {
case EQUAL_TO: {
filter_result = (0 == compare);
} break;
case LESS_EQUAL: {
filter_result = (compare <= 0);
} break;
case NOT_EQUAL: {
filter_result = (compare != 0);
} break;
case LESS_THAN: {
filter_result = (compare < 0);
} break;
case GREAT_EQUAL: {
filter_result = (compare >= 0);
} break;
case GREAT_THAN: {
filter_result = (compare > 0);
} break;
default: {
LOG_WARN("invalid compare type: %d", comp);
} break;
}
if (!filter_result) {
return false;
}
}
return true;
}
// int PredicateOperator::tuple_cell_num() const
// {
// return children_[0]->tuple_cell_num();
// }
// RC PredicateOperator::tuple_cell_spec_at(int index, TupleCellSpec &spec) const
// {
// return children_[0]->tuple_cell_spec_at(index, spec);
// }
/* 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 WangYunlai on 2022/6/27.
//
#pragma once
#include "sql/operator/operator.h"
class FilterStmt;
/**
* PredicateOperator 用于单个表中的记录过滤
* 如果是多个表数据过滤,比如join条件的过滤,需要设计新的predicate或者扩展:w
*/
class PredicateOperator : public Operator
{
public:
PredicateOperator(FilterStmt *filter_stmt)
: filter_stmt_(filter_stmt)
{}
virtual ~PredicateOperator() = default;
RC open() override;
RC next() override;
RC close() override;
Tuple * current_tuple() override;
//int tuple_cell_num() const override;
//RC tuple_cell_spec_at(int index, TupleCellSpec &spec) const override;
private:
bool do_predicate(RowTuple &tuple);
private:
FilterStmt *filter_stmt_ = nullptr;
};
/* 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 WangYunlai on 2022/07/01.
//
#include "common/log/log.h"
#include "sql/operator/project_operator.h"
#include "storage/common/record.h"
#include "storage/common/table.h"
RC ProjectOperator::open()
{
if (children_.size() != 1) {
LOG_WARN("project 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;
}
return RC::SUCCESS;
}
RC ProjectOperator::next()
{
return children_[0]->next();
}
RC ProjectOperator::close()
{
children_[0]->close();
return RC::SUCCESS;
}
Tuple *ProjectOperator::current_tuple()
{
tuple_.set_tuple(children_[0]->current_tuple());
return &tuple_;
}
void ProjectOperator::add_projection(const Table *table, const FieldMeta *field_meta)
{
// 对单表来说,展示的(alias) 字段总是字段名称,
// 对多表查询来说,展示的alias 需要带表名字
TupleCellSpec *spec = new TupleCellSpec(new FieldExpr(table, field_meta));
spec->set_alias(field_meta->name());
tuple_.add_cell_spec(spec);
}
RC ProjectOperator::tuple_cell_spec_at(int index, const TupleCellSpec *&spec) const
{
return tuple_.cell_spec_at(index, spec);
}
/* 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 WangYunlai on 2022/07/01.
//
#pragma once
#include "sql/operator/operator.h"
#include "rc.h"
class ProjectOperator : public Operator
{
public:
ProjectOperator()
{}
virtual ~ProjectOperator() = default;
void add_projection(const Table *table, const FieldMeta *field);
RC open() override;
RC next() override;
RC close() override;
int tuple_cell_num() const
{
return tuple_.cell_num();
}
RC tuple_cell_spec_at(int index, const TupleCellSpec *&spec) const;
Tuple * current_tuple() override;
private:
ProjectTuple tuple_;
};
/* 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 WangYunlai on 2021/6/9.
//
#include "sql/operator/table_scan_operator.h"
#include "storage/common/table.h"
#include "rc.h"
RC TableScanOperator::open()
{
RC rc = table_->get_record_scanner(record_scanner_);
if (rc == RC::SUCCESS) {
tuple_.set_schema(table_, table_->table_meta().field_metas());
}
return rc;
}
RC TableScanOperator::next()
{
if (!record_scanner_.has_next()) {
return RC::RECORD_EOF;
}
RC rc = record_scanner_.next(current_record_);
return rc;
}
RC TableScanOperator::close()
{
return record_scanner_.close_scan();
}
Tuple * TableScanOperator::current_tuple()
{
tuple_.set_record(&current_record_);
return &tuple_;
}
// RC TableScanOperator::tuple_cell_spec_at(int index, TupleCellSpec &spec) const
// {
// return tuple_.cell_spec_at(index, spec);
// }
/* 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 WangYunlai on 2021/6/7.
//
#pragma once
#include "sql/operator/operator.h"
#include "storage/common/record_manager.h"
#include "rc.h"
class Table;
class TableScanOperator : public Operator
{
public:
TableScanOperator(Table *table)
: table_(table)
{}
virtual ~TableScanOperator() = default;
RC open() override;
RC next() override;
RC close() override;
Tuple * current_tuple() override;
// int tuple_cell_num() const override
// {
// return tuple_.cell_num();
// }
// RC tuple_cell_spec_at(int index, TupleCellSpec &spec) const override;
private:
Table *table_ = nullptr;
RecordFileScanner record_scanner_;
Record current_record_;
RowTuple tuple_;
};
......@@ -65,7 +65,7 @@ bool OptimizeStage::initialize()
LOG_TRACE("Enter");
std::list<Stage *>::iterator stgp = next_stage_list_.begin();
execute_stage = *(stgp++);
execute_stage_ = *(stgp++);
LOG_TRACE("Exit");
return true;
......@@ -84,7 +84,7 @@ void OptimizeStage::handle_event(StageEvent *event)
LOG_TRACE("Enter\n");
// optimize sql plan, here just pass the event to the next stage
execute_stage->handle_event(event);
execute_stage_->handle_event(event);
LOG_TRACE("Exit\n");
return;
......@@ -93,7 +93,6 @@ void OptimizeStage::handle_event(StageEvent *event)
void OptimizeStage::callback_event(StageEvent *event, CallbackContext *context)
{
LOG_TRACE("Enter\n");
LOG_TRACE("Exit\n");
return;
}
......@@ -34,7 +34,7 @@ protected:
protected:
private:
Stage *execute_stage = nullptr;
Stage *execute_stage_ = nullptr;
};
#endif //__OBSERVER_SQL_OPTIMIZE_STAGE_H__
......@@ -40,7 +40,13 @@ typedef enum {
} CompOp;
//属性值类型
typedef enum { UNDEFINED, CHARS, INTS, FLOATS } AttrType;
typedef enum
{
UNDEFINED,
CHARS,
INTS,
FLOATS
} AttrType;
//属性值
typedef struct _Value {
......@@ -238,4 +244,4 @@ void query_destroy(Query *query); // reset and delete
}
#endif // __cplusplus
#endif // __OBSERVER_SQL_PARSER_PARSE_DEFS_H__
\ No newline at end of file
#endif // __OBSERVER_SQL_PARSER_PARSE_DEFS_H__
......@@ -25,7 +25,6 @@ See the Mulan PSL v2 for more details. */
#include "event/session_event.h"
#include "event/sql_event.h"
#include "sql/parser/parse.h"
#include "event/execution_plan_event.h"
using namespace common;
......@@ -69,7 +68,8 @@ bool ParseStage::initialize()
LOG_TRACE("Enter");
std::list<Stage *>::iterator stgp = next_stage_list_.begin();
optimize_stage_ = *(stgp++);
// optimize_stage_ = *(stgp++);
resolve_stage_ = *(stgp++);
LOG_TRACE("Exit");
return true;
......@@ -87,10 +87,9 @@ void ParseStage::handle_event(StageEvent *event)
{
LOG_TRACE("Enter\n");
StageEvent *new_event = handle_request(event);
if (nullptr == new_event) {
RC rc = handle_request(event);
if (RC::SUCCESS != rc) {
callback_event(event, nullptr);
event->done_immediate();
return;
}
......@@ -98,11 +97,12 @@ void ParseStage::handle_event(StageEvent *event)
if (cb == nullptr) {
LOG_ERROR("Failed to new callback for SQLStageEvent");
callback_event(event, nullptr);
event->done_immediate();
return;
}
event->push_callback(cb);
optimize_stage_->handle_event(new_event);
resolve_stage_->handle_event(event);
event->done_immediate();
LOG_TRACE("Exit\n");
return;
......@@ -113,31 +113,30 @@ void ParseStage::callback_event(StageEvent *event, CallbackContext *context)
LOG_TRACE("Enter\n");
SQLStageEvent *sql_event = static_cast<SQLStageEvent *>(event);
sql_event->session_event()->done_immediate();
sql_event->done_immediate();
LOG_TRACE("Exit\n");
return;
}
StageEvent *ParseStage::handle_request(StageEvent *event)
RC ParseStage::handle_request(StageEvent *event)
{
SQLStageEvent *sql_event = static_cast<SQLStageEvent *>(event);
const std::string &sql = sql_event->get_sql();
const std::string &sql = sql_event->sql();
Query *result = query_create();
if (nullptr == result) {
Query *query_result = query_create();
if (nullptr == query_result) {
LOG_ERROR("Failed to create query.");
return nullptr;
return RC::INTERNAL;
}
RC ret = parse(sql.c_str(), result);
RC ret = parse(sql.c_str(), query_result);
if (ret != RC::SUCCESS) {
// set error information to event
const char *error = result->sstr.errors != nullptr ? result->sstr.errors : "Unknown error";
char response[256];
snprintf(response, sizeof(response), "Failed to parse sql: %s, error msg: %s\n", sql.c_str(), error);
sql_event->session_event()->set_response(response);
query_destroy(result);
return nullptr;
sql_event->session_event()->set_response("Failed to parse sql\n");
query_destroy(query_result);
return RC::INTERNAL;
}
return new ExecutionPlanEvent(sql_event, result);
sql_event->set_query(query_result);
return RC::SUCCESS;
}
......@@ -16,6 +16,7 @@ See the Mulan PSL v2 for more details. */
#define __OBSERVER_SQL_PARSE_STAGE_H__
#include "common/seda/stage.h"
#include "rc.h"
class ParseStage : public common::Stage {
public:
......@@ -33,10 +34,11 @@ protected:
void callback_event(common::StageEvent *event, common::CallbackContext *context);
protected:
common::StageEvent *handle_request(common::StageEvent *event);
RC handle_request(common::StageEvent *event);
private:
Stage *optimize_stage_ = nullptr;
Stage *resolve_stage_ = nullptr;
};
#endif //__OBSERVER_SQL_PARSE_STAGE_H__
......@@ -23,6 +23,9 @@ See the Mulan PSL v2 for more details. */
#include "common/log/log.h"
#include "common/seda/timer_stage.h"
#include "event/sql_event.h"
#include "event/session_event.h"
#include "session/session.h"
#include "sql/stmt/stmt.h"
using namespace common;
......@@ -66,7 +69,7 @@ bool ResolveStage::initialize()
LOG_TRACE("Enter");
std::list<Stage *>::iterator stgp = next_stage_list_.begin();
query_cache_stage = *(stgp++);
query_cache_stage_ = *(stgp++);
LOG_TRACE("Exit");
return true;
......@@ -85,9 +88,31 @@ void ResolveStage::handle_event(StageEvent *event)
LOG_TRACE("Enter\n");
SQLStageEvent *sql_event = static_cast<SQLStageEvent *>(event);
if (nullptr == sql_event) {
LOG_WARN("failed to get sql stage event");
return;
}
SessionEvent *session_event = sql_event->session_event();
Db *db = session_event->session()->get_current_db();
if (nullptr == db) {
LOG_ERROR("cannot current db");
return ;
}
Query *query = sql_event->query();
Stmt *stmt = nullptr;
RC rc = Stmt::create_stmt(db, *query, stmt);
if (rc != RC::SUCCESS && rc != RC::UNIMPLENMENT) {
LOG_WARN("failed to create stmt. rc=%d:%s", rc, strrc(rc));
session_event->set_response("FAILURE\n");
return;
}
sql_event->set_stmt(stmt);
// do nothing here
query_cache_stage->handle_event(sql_event);
query_cache_stage_->handle_event(sql_event);
LOG_TRACE("Exit\n");
return;
......
......@@ -34,7 +34,7 @@ protected:
protected:
private:
Stage *query_cache_stage = nullptr;
Stage *query_cache_stage_ = nullptr;
};
#endif //__OBSERVER_SQL_RESOLVE_STAGE_H__
......@@ -65,8 +65,8 @@ bool PlanCacheStage::initialize()
LOG_TRACE("Enter");
std::list<Stage *>::iterator stgp = next_stage_list_.begin();
execute_stage = *(stgp++);
parse_stage = *(stgp++);
// execute_stage = *(stgp++);
parse_stage_ = *(stgp++);
LOG_TRACE("Exit");
return true;
......@@ -96,7 +96,7 @@ void PlanCacheStage::handle_event(StageEvent *event)
event->push_callback(cb);
*/
// do nothing here, pass the event to the next stage
parse_stage->handle_event(event);
parse_stage_->handle_event(event);
LOG_TRACE("Exit\n");
return;
......
......@@ -34,8 +34,7 @@ protected:
protected:
private:
Stage *parse_stage = nullptr;
Stage *execute_stage = nullptr;
Stage *parse_stage_ = nullptr;
};
#endif //__OBSERVER_SQL_PLAN_CACHE_STAGE_H__
......@@ -65,7 +65,7 @@ bool QueryCacheStage::initialize()
LOG_TRACE("Enter");
std::list<Stage *>::iterator stgp = next_stage_list_.begin();
plan_cache_stage = *(stgp++);
optimize_stage_ = *(stgp++);
LOG_TRACE("Exit");
return true;
......@@ -83,19 +83,7 @@ void QueryCacheStage::handle_event(StageEvent *event)
{
LOG_TRACE("Enter\n");
// Add callback to update query cache
/*
CompletionCallback *cb = new (std::nothrow) CompletionCallback(this, nullptr);
if (cb == nullptr) {
LOG_ERROR("Failed to new callback for SQLStageEvent");
event->done_immediate();
return;
}
event->push_callback(cb);
*/
// do nothing here, pass the event to the next stage
plan_cache_stage->handle_event(event);
optimize_stage_->handle_event(event);
LOG_TRACE("Exit\n");
return;
......@@ -104,10 +92,6 @@ void QueryCacheStage::handle_event(StageEvent *event)
void QueryCacheStage::callback_event(StageEvent *event, CallbackContext *context)
{
LOG_TRACE("Enter\n");
// update data to query cache here
// event->done_immediate();
LOG_TRACE("Exit\n");
return;
}
......@@ -34,7 +34,7 @@ protected:
protected:
private:
Stage *plan_cache_stage = nullptr;
Stage *optimize_stage_ = nullptr;
};
#endif //__OBSERVER_SQL_QUERY_CACHE_STAGE_H__
/* 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 Wangyunlai on 2022/5/22.
//
#include "common/log/log.h"
#include "sql/stmt/delete_stmt.h"
#include "sql/stmt/filter_stmt.h"
#include "storage/common/db.h"
#include "storage/common/table.h"
DeleteStmt::DeleteStmt(Table *table, FilterStmt *filter_stmt)
: table_ (table), filter_stmt_(filter_stmt)
{}
DeleteStmt::~DeleteStmt()
{
if (nullptr != filter_stmt_) {
delete filter_stmt_;
filter_stmt_ = nullptr;
}
}
RC DeleteStmt::create(Db *db, const Deletes &delete_sql, Stmt *&stmt)
{
const char *table_name = delete_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_name=%s", db->name(), table_name);
return RC::SCHEMA_TABLE_NOT_EXIST;
}
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,
delete_sql.conditions, delete_sql.condition_num, filter_stmt);
if (rc != RC::SUCCESS) {
LOG_WARN("failed to create filter statement. rc=%d:%s", rc, strrc(rc));
return rc;
}
stmt = new DeleteStmt(table, filter_stmt);
return rc;
}
/* 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 Wangyunlai on 2022/5/27.
//
#pragma once
#include "rc.h"
#include "sql/stmt/stmt.h"
#include "sql/parser/parse_defs.h"
class Table;
class FilterStmt;
class DeleteStmt : public Stmt
{
public:
DeleteStmt(Table *table, FilterStmt *filter_stmt);
~DeleteStmt() override;
Table *table() const { return table_; }
FilterStmt *filter_stmt() const { return filter_stmt_; }
StmtType type() const override { return StmtType::DELETE; }
public:
static RC create(Db *db, const Deletes &delete_sql, Stmt *&stmt);
private:
Table *table_ = nullptr;
FilterStmt *filter_stmt_ = nullptr;
};
/* 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 Wangyunlai on 2022/5/22.
//
#include "rc.h"
#include "common/log/log.h"
#include "common/lang/string.h"
#include "sql/stmt/filter_stmt.h"
#include "storage/common/db.h"
#include "storage/common/table.h"
FilterStmt::~FilterStmt()
{
for (FilterUnit *unit : filter_units_) {
delete unit;
}
filter_units_.clear();
}
RC FilterStmt::create(Db *db, Table *default_table, std::unordered_map<std::string, Table *> *tables,
const Condition *conditions, int condition_num,
FilterStmt *&stmt)
{
RC rc = RC::SUCCESS;
stmt = nullptr;
FilterStmt *tmp_stmt = new FilterStmt();
for (int i = 0; i < condition_num; i++) {
FilterUnit *filter_unit = nullptr;
rc = create_filter_unit(db, default_table, tables, conditions[i], filter_unit);
if (rc != RC::SUCCESS) {
delete tmp_stmt;
LOG_WARN("failed to create filter unit. condition index=%d", i);
return rc;
}
tmp_stmt->filter_units_.push_back(filter_unit);
}
stmt = tmp_stmt;
return rc;
}
RC get_table_and_field(Db *db, Table *default_table, std::unordered_map<std::string, Table *> *tables,
const RelAttr &attr, Table *&table, const FieldMeta *&field)
{
if (common::is_blank(attr.relation_name)) {
table = default_table;
} else if (nullptr != tables) {
auto iter = tables->find(std::string(attr.relation_name));
if (iter != tables->end()) {
table = iter->second;
}
} else {
table = db->find_table(attr.relation_name);
}
if (nullptr == table) {
LOG_WARN("No such table: attr.relation_name: %s", attr.relation_name);
return RC::SCHEMA_TABLE_NOT_EXIST;
}
field = table->table_meta().field(attr.attribute_name);
if (nullptr == field) {
LOG_WARN("no such field in table: table %s, field %s", table->name(), attr.attribute_name);
table = nullptr;
return RC::SCHEMA_FIELD_NOT_EXIST;
}
return RC::SUCCESS;
}
RC FilterStmt::create_filter_unit(Db *db, Table *default_table, std::unordered_map<std::string, Table *> *tables,
const Condition &condition, FilterUnit *&filter_unit)
{
RC rc = RC::SUCCESS;
CompOp comp = condition.comp;
if (comp < EQUAL_TO || comp >= NO_OP) {
LOG_WARN("invalid compare operator : %d", comp);
return RC::INVALID_ARGUMENT;
}
Expression *left = nullptr;
Expression *right = nullptr;
if (condition.left_is_attr) {
Table *table = nullptr;
const FieldMeta *field = nullptr;
rc = get_table_and_field(db, default_table, tables, condition.left_attr, table, field);
if (rc != RC::SUCCESS) {
LOG_WARN("cannot find attr");
return rc;
}
left = new FieldExpr(table, field);
} else {
left = new ValueExpr(condition.left_value);
}
if (condition.right_is_attr) {
Table *table = nullptr;
const FieldMeta *field = nullptr;
rc = get_table_and_field(db, default_table, tables, condition.right_attr, table, field);
if (rc != RC::SUCCESS) {
LOG_WARN("cannot find attr");
delete left;
return rc;
}
right = new FieldExpr(table, field);
} else {
right = new ValueExpr(condition.right_value);
}
filter_unit = new FilterUnit;
filter_unit->set_comp(comp);
filter_unit->set_left(left);
filter_unit->set_right(right);
// 检查两个类型是否能够比较
return rc;
}
/* 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 Wangyunlai on 2022/5/22.
//
#pragma once
#include <vector>
#include <unordered_map>
#include "rc.h"
#include "sql/parser/parse_defs.h"
#include "sql/stmt/stmt.h"
#include "sql/expr/expression.h"
class Db;
class Table;
class FieldMeta;
class FilterUnit
{
public:
FilterUnit() = default;
~FilterUnit()
{
if (left_) {
delete left_;
left_ = nullptr;
}
if (right_) {
delete right_;
right_ = nullptr;
}
}
void set_comp(CompOp comp) {
comp_ = comp;
}
CompOp comp() const {
return comp_;
}
void set_left(Expression *expr)
{
left_ = expr;
}
void set_right(Expression *expr)
{
right_ = expr;
}
Expression *left() const
{
return left_;
}
Expression *right() const
{
return right_;
}
private:
CompOp comp_ = NO_OP;
Expression *left_ = nullptr;
Expression *right_ = nullptr;
};
class FilterStmt
{
public:
FilterStmt() = default;
virtual ~FilterStmt();
public:
const std::vector<FilterUnit *> &filter_units() const
{
return filter_units_;
}
public:
static RC create(Db *db, Table *default_table, std::unordered_map<std::string, Table *> *tables,
const Condition *conditions, int condition_num,
FilterStmt *&stmt);
static RC create_filter_unit(Db *db, Table *default_table, std::unordered_map<std::string, Table *> *tables,
const Condition &condition, FilterUnit *&filter_unit);
private:
std::vector<FilterUnit *> filter_units_; // 默认当前都是AND关系
};
/* 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 Wangyunlai on 2022/5/22.
//
#include "sql/stmt/insert_stmt.h"
#include "common/log/log.h"
#include "storage/common/db.h"
#include "storage/common/table.h"
InsertStmt::InsertStmt(Table *table, const Value *values, int value_amount)
: table_ (table), values_(values), value_amount_(value_amount)
{}
RC InsertStmt::create(Db *db, const Inserts &inserts, Stmt *&stmt)
{
const char *table_name = inserts.relation_name;
if (nullptr == db || nullptr == table_name || inserts.value_num <= 0) {
LOG_WARN("invalid argument. db=%p, table_name=%p, value_num=%d",
db, table_name, inserts.value_num);
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_name=%s", db->name(), table_name);
return RC::SCHEMA_TABLE_NOT_EXIST;
}
// check the fields number
const Value *values = inserts.values;
const int value_num = inserts.value_num;
const TableMeta &table_meta = table->table_meta();
const int field_num = table_meta.field_num() - table_meta.sys_field_num();
if (field_num != value_num) {
LOG_WARN("schema mismatch. value num=%d, field num in schema=%d", value_num, field_num);
return RC::SCHEMA_FIELD_MISSING;
}
// check fields type
const int sys_field_num = table_meta.sys_field_num();
for (int i = 0; i < value_num; i++) {
const FieldMeta *field_meta = table_meta.field(i + sys_field_num);
const AttrType field_type = field_meta->type();
const AttrType value_type = values[i].type;
if (field_type != value_type) { // TODO try to convert the value type to field type
LOG_WARN("field type mismatch. table=%s, field=%s, field type=%d, value_type=%d",
table_name, field_meta->name(), field_type, value_type);
return RC::SCHEMA_FIELD_TYPE_MISMATCH;
}
}
// everything alright
stmt = new InsertStmt(table, values, value_num);
return RC::SUCCESS;
}
/* 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 Wangyunlai on 2022/5/22.
//
#pragma once
#include "rc.h"
#include "sql/stmt/stmt.h"
class Table;
class Db;
class InsertStmt : public Stmt
{
public:
InsertStmt() = default;
InsertStmt(Table *table, const Value *values, int value_amount);
StmtType type() const override {
return StmtType::INSERT;
}
public:
static RC create(Db *db, const Inserts &insert_sql, Stmt *&stmt);
public:
Table *table() const {return table_;}
const Value *values() const { return values_; }
int value_amount() const { return value_amount_; }
private:
Table *table_ = nullptr;
const Value *values_ = nullptr;
int value_amount_ = 0;
};
/* 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 Wangyunlai on 2022/6/6.
//
#include "sql/stmt/select_stmt.h"
#include "sql/stmt/filter_stmt.h"
#include "common/log/log.h"
#include "common/lang/string.h"
#include "storage/common/db.h"
#include "storage/common/table.h"
SelectStmt::~SelectStmt()
{
if (nullptr != filter_stmt_) {
delete filter_stmt_;
filter_stmt_ = nullptr;
}
}
static void wildcard_fields(Table *table, std::vector<Field> &field_metas)
{
const TableMeta &table_meta = table->table_meta();
const int field_num = table_meta.field_num();
for (int i = table_meta.sys_field_num(); i < field_num; i++) {
field_metas.push_back(Field(table, table_meta.field(i)));
}
}
RC SelectStmt::create(Db *db, const Selects &select_sql, Stmt *&stmt)
{
if (nullptr == db) {
LOG_WARN("invalid argument. db is null");
return RC::INVALID_ARGUMENT;
}
// collect tables in `from` statement
std::vector<Table *> tables;
std::unordered_map<std::string, Table *> table_map;
for (int i = 0; i < select_sql.relation_num; i++) {
const char *table_name = select_sql.relations[i];
if (nullptr == table_name) {
LOG_WARN("invalid argument. relation name is null. index=%d", i);
return RC::INVALID_ARGUMENT;
}
Table *table = db->find_table(table_name);
if (nullptr == table) {
LOG_WARN("no such table. db=%s, table_name=%s", db->name(), table_name);
return RC::SCHEMA_TABLE_NOT_EXIST;
}
tables.push_back(table);
table_map.insert(std::pair<std::string, Table*>(table_name, table));
}
// collect query fields in `select` statement
std::vector<Field> query_fields;
for (int i = select_sql.attr_num - 1; i >= 0; i--) {
const RelAttr &relation_attr = select_sql.attributes[i];
if (common::is_blank(relation_attr.relation_name) && 0 == strcmp(relation_attr.attribute_name, "*")) {
for (Table *table : tables) {
wildcard_fields(table, query_fields);
}
} else if (!common::is_blank(relation_attr.relation_name)) { // TODO
const char *table_name = relation_attr.relation_name;
const char *field_name = relation_attr.attribute_name;
if (0 == strcmp(table_name, "*")) {
if (0 != strcmp(field_name, "*")) {
LOG_WARN("invalid field name while table is *. attr=%s", field_name);
return RC::SCHEMA_FIELD_MISSING;
}
for (Table *table : tables) {
wildcard_fields(table, query_fields);
}
} else {
auto iter = table_map.find(table_name);
if (iter == table_map.end()) {
LOG_WARN("no such table in from list: %s", table_name);
return RC::SCHEMA_FIELD_MISSING;
}
Table *table = iter->second;
if (0 == strcmp(field_name, "*")) {
wildcard_fields(table, query_fields);
} else {
const FieldMeta *field_meta = table->table_meta().field(field_name);
if (nullptr == field_meta) {
LOG_WARN("no such field. field=%s.%s.%s", db->name(), table->name(), field_name);
return RC::SCHEMA_FIELD_MISSING;
}
query_fields.push_back(Field(table, field_meta));
}
}
} else {
if (tables.size() != 1) {
LOG_WARN("invalid. I do not know the attr's table. attr=%s", relation_attr.attribute_name);
return RC::SCHEMA_FIELD_MISSING;
}
Table *table = tables[0];
const FieldMeta *field_meta = table->table_meta().field(relation_attr.attribute_name);
if (nullptr == field_meta) {
LOG_WARN("no such field. field=%s.%s.%s", db->name(), table->name(), relation_attr.attribute_name);
return RC::SCHEMA_FIELD_MISSING;
}
query_fields.push_back(Field(table, field_meta));
}
}
LOG_INFO("got %d tables in from stmt and %d fields in query stmt", tables.size(), query_fields.size());
Table *default_table = nullptr;
if (tables.size() == 1) {
default_table = tables[0];
}
// create filter statement in `where` statement
FilterStmt *filter_stmt = nullptr;
RC rc = FilterStmt::create(db, default_table, &table_map,
select_sql.conditions, select_sql.condition_num, filter_stmt);
if (rc != RC::SUCCESS) {
LOG_WARN("cannot construct filter stmt");
return rc;
}
// everything alright
SelectStmt *select_stmt = new SelectStmt();
select_stmt->tables_.swap(tables);
select_stmt->query_fields_.swap(query_fields);
select_stmt->filter_stmt_ = filter_stmt;
stmt = select_stmt;
return RC::SUCCESS;
}
......@@ -9,42 +9,41 @@ MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */
//
// Created by Meiyi & Wangyunlai on 2021/5/13.
// Created by Wangyunlai on 2022/6/5.
//
#ifndef __OBSERVER_SQL_EXECUTOR_EXECUTION_NODE_H_
#define __OBSERVER_SQL_EXECUTOR_EXECUTION_NODE_H_
#pragma once
#include <vector>
#include "storage/common/condition_filter.h"
#include "sql/executor/tuple.h"
#include "rc.h"
#include "sql/stmt/stmt.h"
#include "storage/common/field.h"
class FieldMeta;
class FilterStmt;
class Db;
class Table;
class Trx;
class ExecutionNode {
class SelectStmt : public Stmt
{
public:
ExecutionNode() = default;
virtual ~ExecutionNode() = default;
virtual RC execute(TupleSet &tuple_set) = 0;
};
SelectStmt() = default;
~SelectStmt() override;
class SelectExeNode : public ExecutionNode {
StmtType type() const override { return StmtType::SELECT; }
public:
SelectExeNode();
virtual ~SelectExeNode();
static RC create(Db *db, const Selects &select_sql, Stmt *&stmt);
RC init(
Trx *trx, Table *table, TupleSchema &&tuple_schema, std::vector<DefaultConditionFilter *> &&condition_filters);
RC execute(TupleSet &tuple_set) override;
public:
const std::vector<Table *> &tables() const { return tables_; }
const std::vector<Field> &query_fields() const { return query_fields_; }
FilterStmt *filter_stmt() const { return filter_stmt_; }
private:
Trx *trx_ = nullptr;
Table *table_;
TupleSchema tuple_schema_;
std::vector<DefaultConditionFilter *> condition_filters_;
std::vector<Field> query_fields_;
std::vector<Table *> tables_;
FilterStmt *filter_stmt_ = nullptr;
};
#endif //__OBSERVER_SQL_EXECUTOR_EXECUTION_NODE_H_
/* 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 Wangyunlai on 2022/5/22.
//
#include "rc.h"
#include "common/log/log.h"
#include "sql/stmt/insert_stmt.h"
#include "sql/stmt/delete_stmt.h"
#include "sql/stmt/select_stmt.h"
RC Stmt::create_stmt(Db *db, const Query &query, Stmt *&stmt)
{
stmt = nullptr;
switch (query.flag) {
case SCF_INSERT: {
return InsertStmt::create(db, query.sstr.insertion, stmt);
}
break;
case SCF_DELETE: {
return DeleteStmt::create(db, query.sstr.deletion, stmt);
}
case SCF_SELECT: {
return SelectStmt::create(db, query.sstr.selection, stmt);
}
default: {
LOG_WARN("unknown query command");
}
break;
}
return RC::UNIMPLENMENT;
}
/* 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 Wangyunlai on 2022/5/22.
//
#pragma once
#include "rc.h"
#include "sql/parser/parse_defs.h"
class Db;
enum class StmtType
{
SELECT,
INSERT,
UPDATE,
DELETE,
CREATE_TABLE,
DROP_TABLE,
CREATE_INDEX,
DROP_INDEX,
SYNC,
SHOW_TABLES,
DESC_TABLE,
BEGIN,
COMMIT,
ROLLBACK,
LOAD_DATA,
HELP,
EXIT,
PREDICATE,
};
class Stmt
{
public:
Stmt() = default;
virtual ~Stmt() = default;
virtual StmtType type() const = 0;
public:
static RC create_stmt(Db *db, const Query &query, Stmt *&stmt);
private:
};
......@@ -9,20 +9,18 @@ MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */
//
// Created by Longda on 2021/4/14.
// Created by Wangyunlai on 2022/5/22.
//
#include "event/storage_event.h"
#include "event/execution_plan_event.h"
#include "sql/stmt/update_stmt.h"
StorageEvent::StorageEvent(ExecutionPlanEvent *exe_event) : exe_event_(exe_event)
UpdateStmt::UpdateStmt(Table *table, Value *values, int value_amount)
: table_ (table), values_(values), value_amount_(value_amount)
{}
StorageEvent::~StorageEvent()
RC UpdateStmt::create(Db *db, const Updates &update, Stmt *&stmt)
{
exe_event_ = nullptr;
// if (exe_event_ != nullptr) {
// ExecutionPlanEvent *exe_event = exe_event_;
// exe_event->doneImmediate();
// }
}
\ No newline at end of file
// TODO
stmt = nullptr;
return RC::INTERNAL;
}
/* 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 Wangyunlai on 2022/5/22.
//
#pragma once
#include "rc.h"
#include "sql/stmt/stmt.h"
class Table;
class UpdateStmt : public Stmt
{
public:
UpdateStmt() = default;
UpdateStmt(Table *table, Value *values, int value_amount);
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_; }
private:
Table *table_ = nullptr;
Value *values_ = nullptr;
int value_amount_ = 0;
};
......@@ -129,13 +129,13 @@ bool DefaultConditionFilter::filter(const Record &rec) const
char *right_value = nullptr;
if (left_.is_attr) { // value
left_value = (char *)(rec.data + left_.attr_offset);
left_value = (char *)(rec.data() + left_.attr_offset);
} else {
left_value = (char *)left_.value;
}
if (right_.is_attr) {
right_value = (char *)(rec.data + right_.attr_offset);
right_value = (char *)(rec.data() + right_.attr_offset);
} else {
right_value = (char *)right_.value;
}
......
......@@ -18,7 +18,7 @@ See the Mulan PSL v2 for more details. */
#include "rc.h"
#include "sql/parser/parse.h"
struct Record;
class Record;
class Table;
struct ConDesc {
......@@ -101,4 +101,4 @@ private:
bool memory_owner_ = false; // filters_的内存是否由自己来控制
};
#endif // __OBSERVER_STORAGE_COMMON_CONDITION_FILTER_H_
\ No newline at end of file
#endif // __OBSERVER_STORAGE_COMMON_CONDITION_FILTER_H_
/* 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 Wangyunlai on 2022/07/05.
//
#pragma once
#include "storage/common/table.h"
#include "storage/common/field_meta.h"
class Field
{
public:
Field() = default;
Field(const Table *table, const FieldMeta *field) : table_(table), field_(field)
{}
const Table *table() const { return table_; }
const FieldMeta *meta() const { return field_; }
AttrType attr_type() const
{
return field_->type();
}
const char *table_name() const { return table_->name(); }
const char *field_name() const { return field_->name(); }
void set_table(const Table *table)
{
this->table_ = table;
}
void set_field(const FieldMeta *field)
{
this->field_ = field;
}
private:
const Table *table_ = nullptr;
const FieldMeta *field_ = nullptr;
};
/* 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 Wangyunlai on 2022/5/4.
//
#pragma once
#include <stddef.h>
#include <vector>
#include <limits>
#include <sstream>
#include "rc.h"
#include "defs.h"
#include "storage/common/index_meta.h"
#include "storage/common/field_meta.h"
class Field;
struct RID {
PageNum page_num; // record's page number
SlotNum slot_num; // record's slot number
// bool valid; // true means a valid record
RID() = default;
RID(const PageNum _page_num, const SlotNum _slot_num)
: page_num(_page_num), slot_num(_slot_num)
{}
const std::string to_string() const
{
std::stringstream ss;
ss << "PageNum:" << page_num << ", SlotNum:" << slot_num;
return ss.str();
}
bool operator==(const RID &other) const
{
return page_num == other.page_num && slot_num == other.slot_num;
}
bool operator!=(const RID &other) const
{
return !(*this == other);
}
static int compare(const RID *rid1, const RID *rid2)
{
int page_diff = rid1->page_num - rid2->page_num;
if (page_diff != 0) {
return page_diff;
} else {
return rid1->slot_num - rid2->slot_num;
}
}
/**
* 返回一个不可能出现的最小的RID
* 虽然page num 0和slot num 0都是合法的,但是page num 0通常用于存放meta数据,所以对数据部分来说都是
* 不合法的. 这里在bplus tree中查找时会用到。
*/
static RID *min()
{
static RID rid{0, 0};
return &rid;
}
static RID *max()
{
static RID rid{std::numeric_limits<PageNum>::max(), std::numeric_limits<SlotNum>::max()};
return &rid;
}
};
class Record
{
public:
Record() = default;
~Record() = default;
void set_data(char *data) { this->data_ = data; }
char *data() { return this->data_; }
const char *data() const { return this->data_; }
void set_rid(const RID &rid) { this->rid_ = rid; }
void set_rid(const PageNum page_num, const SlotNum slot_num) { this->rid_.page_num = page_num; this->rid_.slot_num = slot_num; }
RID & rid() { return rid_; }
const RID &rid() const { return rid_; };
private:
RID rid_;
// the data buffer
// record will not release the memory
char * data_ = nullptr;
};
......@@ -67,14 +67,13 @@ bool RecordPageIterator::has_next()
RC RecordPageIterator::next(Record &record)
{
record.rid.page_num = page_num_;
record.rid.slot_num = next_slot_num_;
record.data = record_page_handler_->get_record_data(record.rid.slot_num);
record.set_rid(page_num_, next_slot_num_);
record.set_data(record_page_handler_->get_record_data(record.rid().slot_num));
if (next_slot_num_ >= 0) {
next_slot_num_ = bitmap_.next_setted_bit(next_slot_num_ + 1);
}
return record.rid.slot_num != -1 ? RC::SUCCESS : RC::RECORD_EOF;
return record.rid().slot_num != -1 ? RC::SUCCESS : RC::RECORD_EOF;
}
////////////////////////////////////////////////////////////////////////////////
......@@ -170,21 +169,21 @@ RC RecordPageHandler::insert_record(const char *data, RID *rid)
RC RecordPageHandler::update_record(const Record *rec)
{
if (rec->rid.slot_num >= page_header_->record_capacity) {
if (rec->rid().slot_num >= page_header_->record_capacity) {
LOG_ERROR("Invalid slot_num %d, exceed page's record capacity, page_num %d.",
rec->rid.slot_num, frame_->page_num());
rec->rid().slot_num, frame_->page_num());
return RC::INVALID_ARGUMENT;
}
Bitmap bitmap(bitmap_, page_header_->record_capacity);
if (!bitmap.get_bit(rec->rid.slot_num)) {
if (!bitmap.get_bit(rec->rid().slot_num)) {
LOG_ERROR("Invalid slot_num %d, slot is empty, page_num %d.",
rec->rid.slot_num, frame_->page_num());
rec->rid().slot_num, frame_->page_num());
return RC::RECORD_RECORD_NOT_EXIST;
} else {
char *record_data = get_record_data(rec->rid.slot_num);
memcpy(record_data, rec->data, page_header_->record_real_size);
bitmap.set_bit(rec->rid.slot_num);
char *record_data = get_record_data(rec->rid().slot_num);
memcpy(record_data, rec->data(), page_header_->record_real_size);
bitmap.set_bit(rec->rid().slot_num);
frame_->mark_dirty();
// LOG_TRACE("Update record. file_id=%d, page num=%d,slot=%d", file_id_, rec->rid.page_num, rec->rid.slot_num);
return RC::SUCCESS;
......@@ -234,8 +233,8 @@ RC RecordPageHandler::get_record(const RID *rid, Record *rec)
return RC::RECORD_RECORD_NOT_EXIST;
}
rec->rid = *rid;
rec->data = get_record_data(rid->slot_num);
rec->set_rid(*rid);
rec->set_data(get_record_data(rid->slot_num));
return RC::SUCCESS;
}
......@@ -328,8 +327,8 @@ RC RecordFileHandler::update_record(const Record *rec)
{
RC ret;
RecordPageHandler page_handler;
if ((ret = page_handler.init(*disk_buffer_pool_, rec->rid.page_num)) != RC::SUCCESS) {
LOG_ERROR("Failed to init record page handler.page number=%d", rec->rid.page_num);
if ((ret = page_handler.init(*disk_buffer_pool_, rec->rid().page_num)) != RC::SUCCESS) {
LOG_ERROR("Failed to init record page handler.page number=%d", rec->rid().page_num);
return ret;
}
......@@ -412,7 +411,7 @@ RC RecordFileScanner::fetch_next_record()
return rc;
}
}
next_record_.rid.slot_num = -1;
next_record_.rid().slot_num = -1;
return RC::RECORD_EOF;
}
......@@ -430,7 +429,7 @@ RC RecordFileScanner::fetch_next_record_in_page()
}
}
next_record_.rid.slot_num = -1;
next_record_.rid().slot_num = -1;
return RC::RECORD_EOF;
}
......@@ -449,7 +448,7 @@ RC RecordFileScanner::close_scan()
bool RecordFileScanner::has_next()
{
return next_record_.rid.slot_num != -1;
return next_record_.rid().slot_num != -1;
}
RC RecordFileScanner::next(Record &record)
......
......@@ -17,10 +17,9 @@ See the Mulan PSL v2 for more details. */
#include <sstream>
#include <limits>
#include "storage/default/disk_buffer_pool.h"
#include "storage/common/record.h"
#include "common/lang/bitmap.h"
typedef int32_t SlotNum;
class ConditionFilter;
struct PageHeader {
......@@ -31,56 +30,6 @@ struct PageHeader {
int32_t first_record_offset; // 第一条记录的偏移量
};
struct RID {
PageNum page_num; // record's page number
SlotNum slot_num; // record's slot number
// bool valid; // true means a valid record
const std::string to_string() const
{
std::stringstream ss;
ss << "PageNum:" << page_num << ", SlotNum:" << slot_num;
return ss.str();
}
bool operator==(const RID &other) const
{
return page_num == other.page_num && slot_num == other.slot_num;
}
bool operator!=(const RID &other) const
{
return !(*this == other);
}
static int compare(const RID *rid1, const RID *rid2)
{
int page_diff = rid1->page_num - rid2->page_num;
if (page_diff != 0) {
return page_diff;
} else {
return rid1->slot_num - rid2->slot_num;
}
}
/**
* 返回一个不可能出现的最小的RID
* 虽然page num 0和slot num 0都是合法的,但是page num 0通常用于存放meta数据,所以对数据部分来说都是
* 不合法的. 这里在bplus tree中查找时会用到。
*/
static RID *min()
{
static RID rid{0, 0};
return &rid;
}
static RID *max()
{
static RID rid{std::numeric_limits<PageNum>::max(), std::numeric_limits<SlotNum>::max()};
return &rid;
}
};
class RidDigest {
public:
......@@ -90,12 +39,6 @@ public:
}
};
struct Record {
// bool valid; // false means the record hasn't been load
RID rid; // record's rid
char *data; // record's data
};
class RecordPageHandler;
class RecordPageIterator
{
......
......@@ -202,7 +202,7 @@ RC Table::rollback_insert(Trx *trx, const RID &rid)
}
// remove all indexes
rc = delete_entry_of_indexes(record.data, rid, false);
rc = delete_entry_of_indexes(record.data(), rid, false);
if (rc != RC::SUCCESS) {
LOG_ERROR("Failed to delete indexes of record(rid=%d.%d) while rollback insert, rc=%d:%s",
rid.page_num,
......@@ -223,7 +223,7 @@ RC Table::insert_record(Trx *trx, Record *record)
if (trx != nullptr) {
trx->init_trx_info(this, *record);
}
rc = record_handler_->insert_record(record->data, table_meta_.record_size(), &record->rid);
rc = record_handler_->insert_record(record->data(), table_meta_.record_size(), &record->rid());
if (rc != RC::SUCCESS) {
LOG_ERROR("Insert record failed. table name=%s, rc=%d:%s", table_meta_.name(), rc, strrc(rc));
return rc;
......@@ -234,7 +234,7 @@ RC Table::insert_record(Trx *trx, Record *record)
if (rc != RC::SUCCESS) {
LOG_ERROR("Failed to log operation(insertion) to trx");
RC rc2 = record_handler_->delete_record(&record->rid);
RC rc2 = record_handler_->delete_record(&record->rid());
if (rc2 != RC::SUCCESS) {
LOG_ERROR("Failed to rollback record data when insert index entries failed. table name=%s, rc=%d:%s",
name(),
......@@ -245,16 +245,16 @@ RC Table::insert_record(Trx *trx, Record *record)
}
}
rc = insert_entry_of_indexes(record->data, record->rid);
rc = insert_entry_of_indexes(record->data(), record->rid());
if (rc != RC::SUCCESS) {
RC rc2 = delete_entry_of_indexes(record->data, record->rid, true);
RC rc2 = delete_entry_of_indexes(record->data(), record->rid(), true);
if (rc2 != RC::SUCCESS) {
LOG_ERROR("Failed to rollback index data when insert index entries failed. table name=%s, rc=%d:%s",
name(),
rc2,
strrc(rc2));
}
rc2 = record_handler_->delete_record(&record->rid);
rc2 = record_handler_->delete_record(&record->rid());
if (rc2 != RC::SUCCESS) {
LOG_PANIC("Failed to rollback record data when insert index entries failed. table name=%s, rc=%d:%s",
name(),
......@@ -280,7 +280,7 @@ RC Table::insert_record(Trx *trx, int value_num, const Value *values)
}
Record record;
record.data = record_data;
record.set_data(record_data);
// record.valid = true;
rc = insert_record(trx, &record);
delete[] record_data;
......@@ -357,6 +357,15 @@ RC Table::init_record_handler(const char *base_dir)
return rc;
}
RC Table::get_record_scanner(RecordFileScanner &scanner)
{
RC rc = scanner.open_scan(*data_buffer_pool_, nullptr);
if (rc != RC::SUCCESS) {
LOG_ERROR("failed to open scanner. rc=%d:%s", rc, strrc(rc));
}
return rc;
}
/**
* 为了不把Record暴露出去,封装一下
*/
......@@ -368,7 +377,7 @@ public:
void consume(const Record *record)
{
record_reader_(record->data, context_);
record_reader_(record->data(), context_);
}
private:
......@@ -383,15 +392,16 @@ static RC scan_record_reader_adapter(Record *record, void *context)
return RC::SUCCESS;
}
RC Table::scan_record(
Trx *trx, ConditionFilter *filter, int limit, void *context, void (*record_reader)(const char *data, void *context))
RC Table::scan_record(Trx *trx, ConditionFilter *filter,
int limit, void *context,
void (*record_reader)(const char *data, void *context))
{
RecordReaderScanAdapter adapter(record_reader, context);
return scan_record(trx, filter, limit, (void *)&adapter, scan_record_reader_adapter);
}
RC Table::scan_record(Trx *trx, ConditionFilter *filter, int limit, void *context,
RC (*record_reader)(Record *record, void *context))
RC (*record_reader)(Record *record, void *context))
{
if (nullptr == record_reader) {
return RC::INVALID_ARGUMENT;
......@@ -439,8 +449,9 @@ RC Table::scan_record(Trx *trx, ConditionFilter *filter, int limit, void *contex
return rc;
}
RC Table::scan_record_by_index(Trx *trx, IndexScanner *scanner, ConditionFilter *filter, int limit, void *context,
RC (*record_reader)(Record *, void *))
RC Table::scan_record_by_index(Trx *trx, IndexScanner *scanner, ConditionFilter *filter,
int limit, void *context,
RC (*record_reader)(Record *, void *))
{
RC rc = RC::SUCCESS;
RID rid;
......@@ -485,7 +496,7 @@ public:
RC insert_index(const Record *record)
{
return index_->insert_entry(record->data, &record->rid);
return index_->insert_entry(record->data(), &record->rid());
}
private:
......@@ -506,9 +517,7 @@ RC Table::create_index(Trx *trx, const char *index_name, const char *attribute_n
}
if (table_meta_.index(index_name) != nullptr || table_meta_.find_index_by_field((attribute_name))) {
LOG_INFO("Invalid input arguments, table name is %s, index %s exist or attribute %s exist index",
name(),
index_name,
attribute_name);
name(), index_name, attribute_name);
return RC::SCHEMA_INDEX_EXIST;
}
......@@ -521,7 +530,8 @@ RC Table::create_index(Trx *trx, const char *index_name, const char *attribute_n
IndexMeta new_index_meta;
RC rc = new_index_meta.init(index_name, *field_meta);
if (rc != RC::SUCCESS) {
LOG_INFO("Failed to init IndexMeta in table:%s, index_name:%s, field_name:%s", name(), index_name, attribute_name);
LOG_INFO("Failed to init IndexMeta in table:%s, index_name:%s, field_name:%s",
name(), index_name, attribute_name);
return rc;
}
......@@ -642,15 +652,12 @@ RC Table::delete_record(Trx *trx, Record *record)
if (trx != nullptr) {
rc = trx->delete_record(this, record);
} else {
rc = delete_entry_of_indexes(record->data, record->rid, false); // 重复代码 refer to commit_delete
rc = delete_entry_of_indexes(record->data(), record->rid(), false); // 重复代码 refer to commit_delete
if (rc != RC::SUCCESS) {
LOG_ERROR("Failed to delete indexes of record (rid=%d.%d). rc=%d:%s",
record->rid.page_num,
record->rid.slot_num,
rc,
strrc(rc));
record->rid().page_num, record->rid().slot_num, rc, strrc(rc));
} else {
rc = record_handler_->delete_record(&record->rid);
rc = record_handler_->delete_record(&record->rid());
}
}
return rc;
......@@ -664,13 +671,10 @@ RC Table::commit_delete(Trx *trx, const RID &rid)
if (rc != RC::SUCCESS) {
return rc;
}
rc = delete_entry_of_indexes(record.data, record.rid, false);
rc = delete_entry_of_indexes(record.data(), record.rid(), false);
if (rc != RC::SUCCESS) {
LOG_ERROR("Failed to delete indexes of record(rid=%d.%d). rc=%d:%s",
rid.page_num,
rid.slot_num,
rc,
strrc(rc)); // panic?
rid.page_num, rid.slot_num, rc, strrc(rc)); // panic?
}
rc = record_handler_->delete_record(&rid);
......@@ -728,6 +732,15 @@ Index *Table::find_index(const char *index_name) const
}
return nullptr;
}
Index *Table::find_index_by_field(const char *field_name) const
{
const TableMeta &table_meta = this->table_meta();
const IndexMeta *index_meta = table_meta.find_index_by_field(field_name);
if (index_meta != nullptr) {
return this->find_index(index_meta->name());
}
return nullptr;
}
IndexScanner *Table::find_index_for_scan(const DefaultConditionFilter &filter)
{
......@@ -836,10 +849,7 @@ RC Table::sync()
rc = index->sync();
if (rc != RC::SUCCESS) {
LOG_ERROR("Failed to flush index's pages. table=%s, index=%s, rc=%d:%s",
name(),
index->index_meta().name(),
rc,
strrc(rc));
name(), index->index_meta().name(), rc, strrc(rc));
return rc;
}
}
......
......@@ -17,12 +17,13 @@ See the Mulan PSL v2 for more details. */
#include "storage/common/table_meta.h"
struct RID;
class Record;
class DiskBufferPool;
class RecordFileHandler;
class RecordFileScanner;
class ConditionFilter;
class DefaultConditionFilter;
struct Record;
struct RID;
class Index;
class IndexScanner;
class RecordDeleter;
......@@ -54,12 +55,20 @@ public:
RC update_record(Trx *trx, const char *attribute_name, const Value *value, int condition_num,
const Condition conditions[], int *updated_count);
RC delete_record(Trx *trx, ConditionFilter *filter, int *deleted_count);
RC delete_record(Trx *trx, Record *record);
RC scan_record(Trx *trx, ConditionFilter *filter, int limit, void *context,
void (*record_reader)(const char *data, void *context));
RC create_index(Trx *trx, const char *index_name, const char *attribute_name);
RC get_record_scanner(RecordFileScanner &scanner);
RecordFileHandler *record_handler() const
{
return record_handler_;
}
public:
const char *name() const;
......@@ -82,7 +91,6 @@ private:
IndexScanner *find_index_for_scan(const DefaultConditionFilter &filter);
RC insert_record(Trx *trx, Record *record);
RC delete_record(Trx *trx, Record *record);
private:
friend class RecordUpdater;
......@@ -95,8 +103,9 @@ private:
RC init_record_handler(const char *base_dir);
RC make_record(int value_num, const Value *values, char *&record_out);
private:
public:
Index *find_index(const char *index_name) const;
Index *find_index_by_field(const char *field_name) const;
private:
std::string base_dir_;
......
......@@ -42,7 +42,8 @@ public:
const FieldMeta *field(int index) const;
const FieldMeta *field(const char *name) const;
const FieldMeta *find_field_by_offset(int offset) const;
int field_num() const;
const std::vector<FieldMeta> *field_metas() const { return &fields_; }
int field_num() const; // sys field included
int sys_field_num() const;
const IndexMeta *index(const char *name) const;
......@@ -73,4 +74,4 @@ protected:
static std::vector<FieldMeta> sys_fields_;
};
#endif // __OBSERVER_STORAGE_COMMON_TABLE_META_H__
\ No newline at end of file
#endif // __OBSERVER_STORAGE_COMMON_TABLE_META_H__
......@@ -97,9 +97,6 @@ public:
* 否则,创建该索引。
* 创建索引的工作包括:①创建并打开索引文件;
* ②逐个扫描被索引的记录,并向索引文件中插入索引项;③关闭索引
* @param indexName
* @param relName
* @param attrName
* @return
*/
RC create_index(
......@@ -118,9 +115,6 @@ public:
* nValues为属性值个数,values为对应的属性值数组。
* 函数根据给定的属性值构建元组,调用记录管理模块的函数插入该元组,
* 然后在该表的每个索引中为该元组创建合适的索引项
* @param relName
* @param nValues
* @param values
* @return
*/
RC insert_record(Trx *trx, const char *dbname, const char *relation_name, int value_num, const Value *values);
......@@ -142,11 +136,6 @@ public:
* 在每一个更新的元组中将属性attrName的值设置为一个新的值。
* 如果没有指定条件,则此方法更新relName中所有元组。
* 如果要更新一个被索引的属性,应当先删除每个被更新元组对应的索引条目,然后插入一个新的索引条目
* @param relName
* @param attrName
* @param value
* @param nConditions
* @param conditions
* @return
*/
RC update_record(Trx *trx, const char *dbname, const char *relation_name, const char *attribute_name,
......
......@@ -29,7 +29,6 @@ See the Mulan PSL v2 for more details. */
#include "storage/common/table.h"
#include "storage/common/table_meta.h"
#include "storage/trx/trx.h"
#include "event/execution_plan_event.h"
#include "event/session_event.h"
#include "event/sql_event.h"
#include "event/storage_event.h"
......@@ -143,21 +142,15 @@ void DefaultStorageStage::handle_event(StageEvent *event)
LOG_TRACE("Enter\n");
TimerStat timerStat(*query_metric_);
StorageEvent *storage_event = static_cast<StorageEvent *>(event);
CompletionCallback *cb = new (std::nothrow) CompletionCallback(this, nullptr);
if (cb == nullptr) {
LOG_ERROR("Failed to new callback for SessionEvent");
storage_event->done_immediate();
return;
}
storage_event->push_callback(cb);
SQLStageEvent *sql_event = static_cast<SQLStageEvent *>(event);
Query *sql = storage_event->exe_event()->sqls();
Query *sql = sql_event->query();
SessionEvent *session_event = storage_event->exe_event()->sql_event()->session_event();
SessionEvent *session_event = sql_event->session_event();
Session *session = session_event->get_client()->session;
const char *current_db = session->get_current_db().c_str();
Db *db = session->get_current_db();
const char *dbname = db->name();
Trx *current_trx = session->current_trx();
......@@ -165,78 +158,6 @@ void DefaultStorageStage::handle_event(StageEvent *event)
char response[256];
switch (sql->flag) {
case SCF_INSERT: { // insert into
const Inserts &inserts = sql->sstr.insertion;
const char *table_name = inserts.relation_name;
rc = handler_->insert_record(current_trx, current_db, table_name, inserts.value_num, inserts.values);
snprintf(response, sizeof(response), "%s\n", rc == RC::SUCCESS ? "SUCCESS" : "FAILURE");
} break;
case SCF_UPDATE: {
const Updates &updates = sql->sstr.update;
const char *table_name = updates.relation_name;
const char *field_name = updates.attribute_name;
int updated_count = 0;
rc = handler_->update_record(current_trx,
current_db,
table_name,
field_name,
&updates.value,
updates.condition_num,
updates.conditions,
&updated_count);
snprintf(response, sizeof(response), "%s\n", rc == RC::SUCCESS ? "SUCCESS" : "FAILURE");
} break;
case SCF_DELETE: {
const Deletes &deletes = sql->sstr.deletion;
const char *table_name = deletes.relation_name;
int deleted_count = 0;
rc = handler_->delete_record(
current_trx, current_db, table_name, deletes.condition_num, deletes.conditions, &deleted_count);
snprintf(response, sizeof(response), "%s\n", rc == RC::SUCCESS ? "SUCCESS" : "FAILURE");
} break;
case SCF_CREATE_TABLE: { // create table
const CreateTable &create_table = sql->sstr.create_table;
rc = handler_->create_table(
current_db, create_table.relation_name, create_table.attribute_count, create_table.attributes);
snprintf(response, sizeof(response), "%s\n", rc == RC::SUCCESS ? "SUCCESS" : "FAILURE");
} break;
case SCF_CREATE_INDEX: {
const CreateIndex &create_index = sql->sstr.create_index;
rc = handler_->create_index(
current_trx, current_db, create_index.relation_name, create_index.index_name, create_index.attribute_name);
snprintf(response, sizeof(response), "%s\n", rc == RC::SUCCESS ? "SUCCESS" : "FAILURE");
} break;
case SCF_SHOW_TABLES: {
Db *db = handler_->find_db(current_db);
if (nullptr == db) {
snprintf(response, sizeof(response), "No such database: %s\n", current_db);
} else {
std::vector<std::string> all_tables;
db->all_tables(all_tables);
if (all_tables.empty()) {
snprintf(response, sizeof(response), "No table\n");
} else {
std::stringstream ss;
for (const auto &table : all_tables) {
ss << table << std::endl;
}
snprintf(response, sizeof(response), "%s\n", ss.str().c_str());
}
}
} break;
case SCF_DESC_TABLE: {
const char *table_name = sql->sstr.desc_table.relation_name;
Table *table = handler_->find_table(current_db, table_name);
std::stringstream ss;
if (table != nullptr) {
table->table_meta().desc(ss);
} else {
ss << "No such table: " << table_name << std::endl;
}
snprintf(response, sizeof(response), "%s", ss.str().c_str());
} break;
case SCF_LOAD_DATA: {
/*
从文件导入数据,如果做性能测试,需要保持这些代码可以正常工作
......@@ -244,7 +165,7 @@ void DefaultStorageStage::handle_event(StageEvent *event)
*/
const char *table_name = sql->sstr.load_data.relation_name;
const char *file_name = sql->sstr.load_data.file_name;
std::string result = load_data(current_db, table_name, file_name);
std::string result = load_data(dbname, table_name, file_name);
snprintf(response, sizeof(response), "%s", result.c_str());
} break;
default:
......@@ -269,7 +190,7 @@ void DefaultStorageStage::callback_event(StageEvent *event, CallbackContext *con
{
LOG_TRACE("Enter\n");
StorageEvent *storage_event = static_cast<StorageEvent *>(event);
storage_event->exe_event()->done_immediate();
storage_event->sql_event()->done_immediate();
LOG_TRACE("Exit\n");
return;
}
......@@ -411,4 +332,4 @@ std::string DefaultStorageStage::load_data(const char *db_name, const char *tabl
<< " record(s) loaded, total cost " << cost_nano / 1000000000.0 << " second(s)" << std::endl;
}
return result_string.str();
}
\ No newline at end of file
}
......@@ -25,11 +25,10 @@ See the Mulan PSL v2 for more details. */
#include <unordered_map>
#include "rc.h"
#include "defs.h"
#include "common/mm/mem_pool.h"
#include "common/lang/bitmap.h"
typedef int32_t PageNum;
class BufferPoolManager;
class DiskBufferPool;
......
......@@ -59,7 +59,7 @@ RC Trx::insert_record(Table *table, Record *record)
{
RC rc = RC::SUCCESS;
// 先校验是否以前是否存在过(应该不会存在)
Operation *old_oper = find_operation(table, record->rid);
Operation *old_oper = find_operation(table, record->rid());
if (old_oper != nullptr) {
return RC::GENERIC_ERROR; // error code
}
......@@ -69,7 +69,7 @@ RC Trx::insert_record(Table *table, Record *record)
// 设置record中trx_field为当前的事务号
// set_record_trx_id(table, record, trx_id_, false);
// 记录到operations中
insert_operation(table, Operation::Type::INSERT, record->rid);
insert_operation(table, Operation::Type::INSERT, record->rid());
return rc;
}
......@@ -77,24 +77,24 @@ RC Trx::delete_record(Table *table, Record *record)
{
RC rc = RC::SUCCESS;
start_if_not_started();
Operation *old_oper = find_operation(table, record->rid);
Operation *old_oper = find_operation(table, record->rid());
if (old_oper != nullptr) {
if (old_oper->type() == Operation::Type::INSERT) {
delete_operation(table, record->rid);
delete_operation(table, record->rid());
return RC::SUCCESS;
} else {
return RC::GENERIC_ERROR;
}
}
set_record_trx_id(table, *record, trx_id_, true);
insert_operation(table, Operation::Type::DELETE, record->rid);
insert_operation(table, Operation::Type::DELETE, record->rid());
return rc;
}
void Trx::set_record_trx_id(Table *table, Record &record, int32_t trx_id, bool deleted) const
{
const FieldMeta *trx_field = table->table_meta().trx_field();
int32_t *ptrx_id = (int32_t *)(record.data + trx_field->offset());
int32_t *ptrx_id = (int32_t *)(record.data() + trx_field->offset());
if (deleted) {
trx_id |= DELETED_FLAG_BIT_MASK;
}
......@@ -104,7 +104,7 @@ void Trx::set_record_trx_id(Table *table, Record &record, int32_t trx_id, bool d
void Trx::get_record_trx_id(Table *table, const Record &record, int32_t &trx_id, bool &deleted)
{
const FieldMeta *trx_field = table->table_meta().trx_field();
int32_t trx = *(int32_t *)(record.data + trx_field->offset());
int32_t trx = *(int32_t *)(record.data() + trx_field->offset());
trx_id = trx & TRX_ID_BIT_MASK;
deleted = (trx & DELETED_FLAG_BIT_MASK) != 0;
}
......@@ -261,4 +261,4 @@ void Trx::start_if_not_started()
if (trx_id_ == 0) {
trx_id_ = next_trx_id();
}
}
\ No newline at end of file
}
/* 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 wangyunlai on 2021/6/11.
//
#include <string.h>
const double epsilon = 1E-6;
int compare_int(void *arg1, void *arg2)
{
int v1 = *(int *)arg1;
int v2 = *(int *)arg2;
return v1 - v2;
}
int compare_float(void *arg1, void *arg2)
{
float v1 = *(float *)arg1;
float v2 = *(float *)arg2;
float cmp = v1 - v2;
if (cmp > epsilon) {
return 1;
}
if (cmp < -epsilon) {
return -1;
}
return 0;
}
int compare_string(void *arg1, void *arg2, int maxlen)
{
const char *s1 = (const char *)arg1;
const char *s2 = (const char *)arg2;
return strncmp(s1, s2, maxlen);
}
/* 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 wangyunlai on 2021/6/11
//
#pragma once
int compare_int(void *arg1, void *arg2);
int compare_float(void *arg1, void *arg2);
int compare_string(void *arg1, void *arg2, int max_length);
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册