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

Merge pull request #42 from hnwyllmm/stmt

implement some operators
./deps/libevent/* ./deps/libevent
./deps/googletest/* ./deps/googletest
./deps/jsoncpp/* ./deps/jsoncpp
build/* build/*
cmake-build-*/* cmake-build-*/*
.vscode/* .vscode/*
...@@ -12,3 +12,7 @@ compile_commands.json ...@@ -12,3 +12,7 @@ compile_commands.json
./vcs.xml ./vcs.xml
./workspace.xml ./workspace.xml
./modules.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 ...@@ -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 \ RUN git clone https://github.com/libevent/libevent -b release-2.1.12-stable \
&& mkdir -p ${HOME_DIR}/deps/libevent/build \ && 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/* && rm -rf ${HOME_DIR}/deps/*
RUN git clone https://github.com/open-source-parsers/jsoncpp.git \ RUN git clone https://github.com/open-source-parsers/jsoncpp.git \
&& mkdir -p ${HOME_DIR}/deps/jsoncpp/build \ && 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/* && rm -rf ${HOME_DIR}/deps/*
RUN git clone https://github.com/google/googletest \ RUN git clone https://github.com/google/googletest \
&& mkdir -p ${HOME_DIR}/deps/googletest/build \ && 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/* && rm -rf ${HOME_DIR}/deps/*
RUN wget http://ftp.gnu.org/gnu/bison/bison-3.7.tar.gz \ 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 ...@@ -57,21 +57,22 @@ count=3
[SessionStage] [SessionStage]
ThreadId=SQLThreads ThreadId=SQLThreads
NextStages=ResolveStage NextStages=PlanCacheStage
[ResolveStage] [PlanCacheStage]
ThreadId=SQLThreads ThreadId=SQLThreads
NextStages=QueryCacheStage #NextStages=OptimizeStage
NextStages=ParseStage
[QueryCacheStage] [ParseStage]
ThreadId=SQLThreads ThreadId=SQLThreads
NextStages=PlanCacheStage NextStages=ResolveStage
[PlanCacheStage] [ResolveStage]
ThreadId=SQLThreads ThreadId=SQLThreads
NextStages=ExecuteStage,ParseStage NextStages=QueryCacheStage
[ParseStage] [QueryCacheStage]
ThreadId=SQLThreads ThreadId=SQLThreads
NextStages=OptimizeStage NextStages=OptimizeStage
......
...@@ -7,3 +7,12 @@ THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, ...@@ -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, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */ 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. ...@@ -9,35 +9,34 @@ MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */ 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__ #pragma once
#define __OBSERVER_EVENT_EXECUTION_PLAN_EVENT_H__
#include "common/seda/stage_event.h" #include "common/seda/stage_event.h"
#include "sql/parser/parse.h"
class SQLStageEvent; class SQLStageEvent;
class Stmt;
class ExecutionPlanEvent : public common::StageEvent { class OptimizeEvent : public common::StageEvent {
public: public:
ExecutionPlanEvent(SQLStageEvent *sql_event, Query *sqls); OptimizeEvent(SQLStageEvent *sql_event, common::StageEvent *parent_event)
virtual ~ExecutionPlanEvent(); : sql_event_(sql_event), parent_event_(parent_event)
{}
Query *sqls() const virtual ~OptimizeEvent() noexcept = default;
{
return sqls_;
}
SQLStageEvent *sql_event() const SQLStageEvent *sql_event() const {
{
return sql_event_; return sql_event_;
} }
common::StageEvent *parent_event() const {
return parent_event_;
}
private: private:
SQLStageEvent *sql_event_; SQLStageEvent *sql_event_ = nullptr;
Query *sqls_; 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. */ ...@@ -15,16 +15,23 @@ See the Mulan PSL v2 for more details. */
#include "session_event.h" #include "session_event.h"
SessionEvent::SessionEvent(ConnectionContext *client) : client_(client) SessionEvent::SessionEvent(ConnectionContext *client) : client_(client)
{} {
}
SessionEvent::~SessionEvent() SessionEvent::~SessionEvent()
{} {
}
ConnectionContext *SessionEvent::get_client() const ConnectionContext *SessionEvent::get_client() const
{ {
return client_; return client_;
} }
Session *SessionEvent::session() const
{
return client_->session;
}
const char *SessionEvent::get_response() const const char *SessionEvent::get_response() const
{ {
return response_.c_str(); return response_.c_str();
...@@ -58,4 +65,4 @@ char *SessionEvent::get_request_buf() ...@@ -58,4 +65,4 @@ char *SessionEvent::get_request_buf()
int SessionEvent::get_request_buf_len() int SessionEvent::get_request_buf_len()
{ {
return SOCKET_BUFFER_SIZE; return SOCKET_BUFFER_SIZE;
} }
\ No newline at end of file
...@@ -21,12 +21,15 @@ See the Mulan PSL v2 for more details. */ ...@@ -21,12 +21,15 @@ See the Mulan PSL v2 for more details. */
#include "common/seda/stage_event.h" #include "common/seda/stage_event.h"
#include "net/connection_context.h" #include "net/connection_context.h"
class Session;
class SessionEvent : public common::StageEvent { class SessionEvent : public common::StageEvent {
public: public:
SessionEvent(ConnectionContext *client); SessionEvent(ConnectionContext *client);
virtual ~SessionEvent(); virtual ~SessionEvent();
ConnectionContext *get_client() const; ConnectionContext *get_client() const;
Session *session() const;
const char *get_response() const; const char *get_response() const;
void set_response(const char *response); void set_response(const char *response);
......
...@@ -15,7 +15,7 @@ See the Mulan PSL v2 for more details. */ ...@@ -15,7 +15,7 @@ See the Mulan PSL v2 for more details. */
#include "event/sql_event.h" #include "event/sql_event.h"
#include "event/session_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 SQLStageEvent::~SQLStageEvent() noexcept
...@@ -26,4 +26,4 @@ SQLStageEvent::~SQLStageEvent() noexcept ...@@ -26,4 +26,4 @@ SQLStageEvent::~SQLStageEvent() noexcept
// session_event_ = nullptr; // session_event_ = nullptr;
// session_event->doneImmediate(); // session_event->doneImmediate();
} }
} }
\ No newline at end of file
...@@ -15,30 +15,37 @@ See the Mulan PSL v2 for more details. */ ...@@ -15,30 +15,37 @@ See the Mulan PSL v2 for more details. */
#ifndef __OBSERVER_SQL_EVENT_SQLEVENT_H__ #ifndef __OBSERVER_SQL_EVENT_SQLEVENT_H__
#define __OBSERVER_SQL_EVENT_SQLEVENT_H__ #define __OBSERVER_SQL_EVENT_SQLEVENT_H__
#include "common/seda/stage_event.h"
#include <string> #include <string>
#include "common/seda/stage_event.h"
class SessionEvent; class SessionEvent;
class Stmt;
struct Query;
class SQLStageEvent : public common::StageEvent { class SQLStageEvent : public common::StageEvent
{
public: public:
SQLStageEvent(SessionEvent *event, std::string &sql); SQLStageEvent(SessionEvent *event, const std::string &sql);
virtual ~SQLStageEvent() noexcept; virtual ~SQLStageEvent() noexcept;
const std::string &get_sql() const
{
return sql_;
}
SessionEvent *session_event() const SessionEvent *session_event() const
{ {
return session_event_; 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: private:
SessionEvent *session_event_; SessionEvent *session_event_ = nullptr;
std::string &sql_; std::string sql_;
// void *context_; Query *query_ = nullptr;
Stmt *stmt_ = nullptr;
}; };
#endif //__SRC_OBSERVER_SQL_EVENT_SQLEVENT_H__ #endif //__SRC_OBSERVER_SQL_EVENT_SQLEVENT_H__
...@@ -17,20 +17,22 @@ See the Mulan PSL v2 for more details. */ ...@@ -17,20 +17,22 @@ See the Mulan PSL v2 for more details. */
#include "common/seda/stage_event.h" #include "common/seda/stage_event.h"
class ExecutionPlanEvent; class SQLStageEvent;
class StorageEvent : public common::StageEvent { class StorageEvent : public common::StageEvent {
public: public:
StorageEvent(ExecutionPlanEvent *exe_event); StorageEvent(SQLStageEvent *sql_event) : sql_event_(sql_event)
{}
virtual ~StorageEvent(); virtual ~StorageEvent();
ExecutionPlanEvent *exe_event() const SQLStageEvent *sql_event() const
{ {
return exe_event_; return sql_event_;
} }
private: private:
ExecutionPlanEvent *exe_event_; SQLStageEvent *sql_event_;
}; };
#endif //__OBSERVER_SQL_EVENT_STORAGEEVENT_H__ #endif //__OBSERVER_SQL_EVENT_STORAGEEVENT_H__
...@@ -24,6 +24,7 @@ const char *strrc(RC rc) ...@@ -24,6 +24,7 @@ const char *strrc(RC rc)
RC_CASE_STRING(SUCCESS); RC_CASE_STRING(SUCCESS);
RC_CASE_STRING(GENERIC_ERROR); RC_CASE_STRING(GENERIC_ERROR);
RC_CASE_STRING(INVALID_ARGUMENT); RC_CASE_STRING(INVALID_ARGUMENT);
RC_CASE_STRING(UNIMPLENMENT);
RC_CASE_STRING(SQL_SYNTAX); RC_CASE_STRING(SQL_SYNTAX);
RC_CASE_STRING(BUFFERPOOL); RC_CASE_STRING(BUFFERPOOL);
RC_CASE_STRING(RECORD); RC_CASE_STRING(RECORD);
...@@ -179,4 +180,4 @@ const char *strrc(RC rc) ...@@ -179,4 +180,4 @@ const char *strrc(RC rc)
return "UNKNOWN"; return "UNKNOWN";
} }
} }
} }
\ No newline at end of file
...@@ -172,10 +172,11 @@ enum RC { ...@@ -172,10 +172,11 @@ enum RC {
/* beginning-of-error-codes */ /* beginning-of-error-codes */
GENERIC_ERROR, /* Generic error */ GENERIC_ERROR, /* Generic error */
INVALID_ARGUMENT, /* Invalid argument */ INVALID_ARGUMENT, /* Invalid argument */
UNIMPLENMENT, /* not implenment yet */
SQL_SYNTAX, /* SQL Syntax error */ SQL_SYNTAX, /* SQL Syntax error */
BUFFERPOOL, /* Buffer pool error*/ BUFFERPOOL, /* Buffer pool error*/
RECORD, /* Record error */ RECORD, /* Record error */
INTERNAL, /* Internal logic error in SQLite */ INTERNAL, /* Internal logic error in SQL */
PERM, /* Access permission denied */ PERM, /* Access permission denied */
ABORT, /* Callback routine requested an abort */ ABORT, /* Callback routine requested an abort */
BUSY, /* The database file is locked */ BUSY, /* The database file is locked */
......
...@@ -14,6 +14,8 @@ See the Mulan PSL v2 for more details. */ ...@@ -14,6 +14,8 @@ See the Mulan PSL v2 for more details. */
#include "session/session.h" #include "session/session.h"
#include "storage/trx/trx.h" #include "storage/trx/trx.h"
#include "storage/common/db.h"
#include "storage/default/default_handler.h"
Session &Session::default_session() Session &Session::default_session()
{ {
...@@ -21,7 +23,7 @@ Session &Session::default_session() ...@@ -21,7 +23,7 @@ Session &Session::default_session()
return session; return session;
} }
Session::Session(const Session &other) : current_db_(other.current_db_) Session::Session(const Session &other) : db_(other.db_)
{} {}
Session::~Session() Session::~Session()
...@@ -30,13 +32,30 @@ Session::~Session() ...@@ -30,13 +32,30 @@ Session::~Session()
trx_ = nullptr; 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) 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) void Session::set_trx_multi_operation_mode(bool multi_operation_mode)
......
...@@ -12,12 +12,12 @@ See the Mulan PSL v2 for more details. */ ...@@ -12,12 +12,12 @@ See the Mulan PSL v2 for more details. */
// Created by Wangyunlai on 2021/5/12. // Created by Wangyunlai on 2021/5/12.
// //
#ifndef __OBSERVER_SESSION_SESSION_H__ #pragma once
#define __OBSERVER_SESSION_SESSION_H__
#include <string> #include <string>
class Trx; class Trx;
class Db;
class Session { class Session {
public: public:
...@@ -31,7 +31,9 @@ public: ...@@ -31,7 +31,9 @@ public:
Session(const Session &other); Session(const Session &other);
void operator=(Session &) = delete; 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_current_db(const std::string &dbname);
void set_trx_multi_operation_mode(bool multi_operation_mode); void set_trx_multi_operation_mode(bool multi_operation_mode);
...@@ -40,9 +42,7 @@ public: ...@@ -40,9 +42,7 @@ public:
Trx *current_trx(); Trx *current_trx();
private: private:
std::string current_db_; Db *db_ = nullptr;
Trx *trx_ = nullptr; Trx *trx_ = nullptr;
bool trx_multi_operation_mode_ = false; // 当前事务的模式,是否多语句模式. 单语句模式自动提交 bool trx_multi_operation_mode_ = false; // 当前事务的模式,是否多语句模式. 单语句模式自动提交
}; };
#endif // __OBSERVER_SESSION_SESSION_H__
\ No newline at end of file
...@@ -34,7 +34,7 @@ using namespace common; ...@@ -34,7 +34,7 @@ using namespace common;
const std::string SessionStage::SQL_METRIC_TAG = "SessionStage.sql"; const std::string SessionStage::SQL_METRIC_TAG = "SessionStage.sql";
// Constructor // 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 // Destructor
...@@ -73,7 +73,7 @@ bool SessionStage::initialize() ...@@ -73,7 +73,7 @@ bool SessionStage::initialize()
LOG_TRACE("Enter"); LOG_TRACE("Enter");
std::list<Stage *>::iterator stgp = next_stage_list_.begin(); std::list<Stage *>::iterator stgp = next_stage_list_.begin();
resolve_stage_ = *(stgp++); plan_cache_stage_ = *(stgp++);
MetricsRegistry &metricsRegistry = get_metrics_registry(); MetricsRegistry &metricsRegistry = get_metrics_registry();
sql_metric_ = new SimpleTimer(); sql_metric_ = new SimpleTimer();
...@@ -138,7 +138,6 @@ void SessionStage::callback_event(StageEvent *event, CallbackContext *context) ...@@ -138,7 +138,6 @@ void SessionStage::callback_event(StageEvent *event, CallbackContext *context)
void SessionStage::handle_request(StageEvent *event) void SessionStage::handle_request(StageEvent *event)
{ {
SessionEvent *sev = dynamic_cast<SessionEvent *>(event); SessionEvent *sev = dynamic_cast<SessionEvent *>(event);
if (nullptr == sev) { if (nullptr == sev) {
LOG_ERROR("Cannot cat event to sessionEvent"); LOG_ERROR("Cannot cat event to sessionEvent");
...@@ -169,5 +168,5 @@ void SessionStage::handle_request(StageEvent *event) ...@@ -169,5 +168,5 @@ void SessionStage::handle_request(StageEvent *event)
sev->push_callback(cb); sev->push_callback(cb);
SQLStageEvent *sql_event = new SQLStageEvent(sev, sql); 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: ...@@ -47,8 +47,8 @@ protected:
void handle_request(common::StageEvent *event); void handle_request(common::StageEvent *event);
private: private:
Stage *resolve_stage_; Stage *plan_cache_stage_ = nullptr;
common::SimpleTimer *sql_metric_; common::SimpleTimer *sql_metric_ = nullptr;
static const std::string SQL_METRIC_TAG; static const std::string SQL_METRIC_TAG;
}; };
......
...@@ -19,24 +19,36 @@ See the Mulan PSL v2 for more details. */ ...@@ -19,24 +19,36 @@ See the Mulan PSL v2 for more details. */
#include "common/io/io.h" #include "common/io/io.h"
#include "common/log/log.h" #include "common/log/log.h"
#include "common/lang/defer.h"
#include "common/seda/timer_stage.h" #include "common/seda/timer_stage.h"
#include "common/lang/string.h" #include "common/lang/string.h"
#include "session/session.h" #include "session/session.h"
#include "event/storage_event.h" #include "event/storage_event.h"
#include "event/sql_event.h" #include "event/sql_event.h"
#include "event/session_event.h" #include "event/session_event.h"
#include "event/execution_plan_event.h" #include "sql/expr/tuple.h"
#include "sql/executor/execution_node.h" #include "sql/operator/table_scan_operator.h"
#include "sql/executor/tuple.h" #include "sql/operator/index_scan_operator.h"
#include "sql/operator/predicate_operator.h"
#include "sql/operator/delete_operator.h"
#include "sql/operator/project_operator.h"
#include "sql/stmt/stmt.h"
#include "sql/stmt/select_stmt.h"
#include "sql/stmt/update_stmt.h"
#include "sql/stmt/delete_stmt.h"
#include "sql/stmt/insert_stmt.h"
#include "sql/stmt/filter_stmt.h"
#include "storage/common/table.h" #include "storage/common/table.h"
#include "storage/common/field.h"
#include "storage/index/index.h"
#include "storage/default/default_handler.h" #include "storage/default/default_handler.h"
#include "storage/common/condition_filter.h" #include "storage/common/condition_filter.h"
#include "storage/trx/trx.h" #include "storage/trx/trx.h"
using namespace common; using namespace common;
RC create_selection_executor( //RC create_selection_executor(
Trx *trx, const Selects &selects, const char *db, const char *table_name, SelectExeNode &select_node); // Trx *trx, const Selects &selects, const char *db, const char *table_name, SelectExeNode &select_node);
//! Constructor //! Constructor
ExecuteStage::ExecuteStage(const char *tag) : Stage(tag) ExecuteStage::ExecuteStage(const char *tag) : Stage(tag)
...@@ -108,9 +120,6 @@ void ExecuteStage::callback_event(StageEvent *event, CallbackContext *context) ...@@ -108,9 +120,6 @@ void ExecuteStage::callback_event(StageEvent *event, CallbackContext *context)
LOG_TRACE("Enter\n"); LOG_TRACE("Enter\n");
// here finish read all data from disk or network, but do nothing here. // here finish read all data from disk or network, but do nothing here.
ExecutionPlanEvent *exe_event = static_cast<ExecutionPlanEvent *>(event);
SQLStageEvent *sql_event = exe_event->sql_event();
sql_event->done_immediate();
LOG_TRACE("Exit\n"); LOG_TRACE("Exit\n");
return; return;
...@@ -118,90 +127,78 @@ void ExecuteStage::callback_event(StageEvent *event, CallbackContext *context) ...@@ -118,90 +127,78 @@ void ExecuteStage::callback_event(StageEvent *event, CallbackContext *context)
void ExecuteStage::handle_request(common::StageEvent *event) void ExecuteStage::handle_request(common::StageEvent *event)
{ {
ExecutionPlanEvent *exe_event = static_cast<ExecutionPlanEvent *>(event); SQLStageEvent *sql_event = static_cast<SQLStageEvent *>(event);
SessionEvent *session_event = exe_event->sql_event()->session_event(); SessionEvent *session_event = sql_event->session_event();
Query *sql = exe_event->sqls(); Stmt *stmt = sql_event->stmt();
const char *current_db = session_event->get_client()->session->get_current_db().c_str(); Session *session = session_event->session();
Query *sql = sql_event->query();
CompletionCallback *cb = new (std::nothrow) CompletionCallback(this, nullptr);
if (cb == nullptr) { if (stmt != nullptr) {
LOG_ERROR("Failed to new callback for ExecutionPlanEvent"); switch (stmt->type()) {
exe_event->done_immediate(); case StmtType::SELECT: {
return; do_select(sql_event);
} } break;
exe_event->push_callback(cb); case StmtType::INSERT: {
do_insert(sql_event);
switch (sql->flag) { } break;
case SCF_SELECT: { // select case StmtType::UPDATE: {
do_select(current_db, sql, exe_event->sql_event()->session_event()); //do_update((UpdateStmt *)stmt, session_event);
exe_event->done_immediate(); } break;
case StmtType::DELETE: {
do_delete(sql_event);
} break;
}
} else {
switch (sql->flag) {
case SCF_HELP: {
do_help(sql_event);
} break;
case SCF_CREATE_TABLE: {
do_create_table(sql_event);
} break;
case SCF_CREATE_INDEX: {
do_create_index(sql_event);
} break;
case SCF_SHOW_TABLES: {
do_show_tables(sql_event);
} break;
case SCF_DESC_TABLE: {
do_desc_table(sql_event);
} break; } break;
case SCF_INSERT:
case SCF_UPDATE:
case SCF_DELETE:
case SCF_CREATE_TABLE:
case SCF_SHOW_TABLES:
case SCF_DESC_TABLE:
case SCF_DROP_TABLE: case SCF_DROP_TABLE:
case SCF_CREATE_INDEX:
case SCF_DROP_INDEX: case SCF_DROP_INDEX:
case SCF_LOAD_DATA: { case SCF_LOAD_DATA: {
StorageEvent *storage_event = new (std::nothrow) StorageEvent(exe_event); default_storage_stage_->handle_event(event);
if (storage_event == nullptr) {
LOG_ERROR("Failed to new StorageEvent");
event->done_immediate();
return;
}
default_storage_stage_->handle_event(storage_event);
} break; } break;
case SCF_SYNC: { case SCF_SYNC: {
RC rc = DefaultHandler::get_default().sync(); RC rc = DefaultHandler::get_default().sync();
session_event->set_response(strrc(rc)); session_event->set_response(strrc(rc));
exe_event->done_immediate();
} break; } break;
case SCF_BEGIN: { case SCF_BEGIN: {
session_event->get_client()->session->set_trx_multi_operation_mode(true); session_event->set_response("SUCCESS\n");
session_event->set_response(strrc(RC::SUCCESS));
exe_event->done_immediate();
} break; } break;
case SCF_COMMIT: { case SCF_COMMIT: {
Trx *trx = session_event->get_client()->session->current_trx(); Trx *trx = session->current_trx();
RC rc = trx->commit(); RC rc = trx->commit();
session_event->get_client()->session->set_trx_multi_operation_mode(false); session->set_trx_multi_operation_mode(false);
session_event->set_response(strrc(rc)); session_event->set_response(strrc(rc));
exe_event->done_immediate();
} break; } break;
case SCF_ROLLBACK: { case SCF_ROLLBACK: {
Trx *trx = session_event->get_client()->session->current_trx(); Trx *trx = session_event->get_client()->session->current_trx();
RC rc = trx->rollback(); RC rc = trx->rollback();
session_event->get_client()->session->set_trx_multi_operation_mode(false); session->set_trx_multi_operation_mode(false);
session_event->set_response(strrc(rc)); session_event->set_response(strrc(rc));
exe_event->done_immediate();
} break;
case SCF_HELP: {
const char *response = "show tables;\n"
"desc `table name`;\n"
"create table `table name` (`column name` `column type`, ...);\n"
"create index `index name` on `table` (`column`);\n"
"insert into `table` values(`value1`,`value2`);\n"
"update `table` set column=value [where `column`=`value`];\n"
"delete from `table` [where `column`=`value`];\n"
"select [ * | `columns` ] from `table`;\n";
session_event->set_response(response);
exe_event->done_immediate();
} break; } break;
case SCF_EXIT: { case SCF_EXIT: {
// do nothing // do nothing
const char *response = "Unsupported\n"; const char *response = "Unsupported\n";
session_event->set_response(response); session_event->set_response(response);
exe_event->done_immediate();
} break; } break;
default: { default: {
exe_event->done_immediate();
LOG_ERROR("Unsupported command=%d\n", sql->flag); LOG_ERROR("Unsupported command=%d\n", sql->flag);
} }
}
} }
} }
...@@ -216,144 +213,349 @@ void end_trx_if_need(Session *session, Trx *trx, bool all_right) ...@@ -216,144 +213,349 @@ void end_trx_if_need(Session *session, Trx *trx, bool all_right)
} }
} }
// 这里没有对输入的某些信息做合法性校验,比如查询的列名、where条件中的列名等,没有做必要的合法性校验 void print_tuple_header(std::ostream &os, const ProjectOperator &oper)
// 需要补充上这一部分. 校验部分也可以放在resolve,不过跟execution放一起也没有关系
RC ExecuteStage::do_select(const char *db, Query *sql, SessionEvent *session_event)
{ {
const int cell_num = oper.tuple_cell_num();
const TupleCellSpec *cell_spec = nullptr;
for (int i = 0; i < cell_num; i++) {
oper.tuple_cell_spec_at(i, cell_spec);
if (i != 0) {
os << " | ";
}
if (cell_spec->alias()) {
os << cell_spec->alias();
}
}
if (cell_num > 0) {
os << '\n';
}
}
void tuple_to_string(std::ostream &os, const Tuple &tuple)
{
TupleCell cell;
RC rc = RC::SUCCESS; RC rc = RC::SUCCESS;
Session *session = session_event->get_client()->session; bool first_field = true;
Trx *trx = session->current_trx(); for (int i = 0; i < tuple.cell_num(); i++) {
const Selects &selects = sql->sstr.selection; rc = tuple.cell_at(i, cell);
// 把所有的表和只跟这张表关联的condition都拿出来,生成最底层的select 执行节点
std::vector<SelectExeNode *> select_nodes;
for (size_t i = 0; i < selects.relation_num; i++) {
const char *table_name = selects.relations[i];
SelectExeNode *select_node = new SelectExeNode;
rc = create_selection_executor(trx, selects, db, table_name, *select_node);
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
delete select_node; LOG_WARN("failed to fetch field of cell. index=%d, rc=%s", i, strrc(rc));
for (SelectExeNode *&tmp_node : select_nodes) { break;
delete tmp_node;
}
end_trx_if_need(session, trx, false);
return rc;
} }
select_nodes.push_back(select_node);
if (!first_field) {
os << " | ";
} else {
first_field = false;
}
cell.to_string(os);
} }
}
if (select_nodes.empty()) { IndexScanOperator *try_to_create_index_scan_operator(FilterStmt *filter_stmt)
LOG_ERROR("No table given"); {
end_trx_if_need(session, trx, false); const std::vector<FilterUnit *> &filter_units = filter_stmt->filter_units();
return RC::SQL_SYNTAX; if (filter_units.empty() ) {
return nullptr;
} }
std::vector<TupleSet> tuple_sets; // 在所有过滤条件中,找到字段与值做比较的条件,然后判断字段是否可以使用索引
for (SelectExeNode *&node : select_nodes) { // 如果是多列索引,这里的处理需要更复杂。
TupleSet tuple_set; // 这里的查找规则是比较简单的,就是尽量找到使用相等比较的索引
rc = node->execute(tuple_set); // 如果没有就找范围比较的,但是直接排除不等比较的索引查询. (你知道为什么?)
if (rc != RC::SUCCESS) { const FilterUnit *better_filter = nullptr;
for (SelectExeNode *&tmp_node : select_nodes) { for (const FilterUnit * filter_unit : filter_units) {
delete tmp_node; if (filter_unit->comp() == NOT_EQUAL) {
continue;
}
Expression *left = filter_unit->left();
Expression *right = filter_unit->right();
if (left->type() == ExprType::FIELD && right->type() == ExprType::VALUE) {
} else if (left->type() == ExprType::VALUE && right->type() == ExprType::FIELD) {
std::swap(left, right);
}
FieldExpr &left_field_expr = *(FieldExpr *)left;
const Field &field = left_field_expr.field();
const Table *table = field.table();
Index *index = table->find_index_by_field(field.field_name());
if (index != nullptr) {
if (better_filter == nullptr) {
better_filter = filter_unit;
} else if (filter_unit->comp() == EQUAL_TO) {
better_filter = filter_unit;
break;
} }
end_trx_if_need(session, trx, false);
return rc;
} else {
tuple_sets.push_back(std::move(tuple_set));
} }
} }
if (better_filter == nullptr) {
return nullptr;
}
Expression *left = better_filter->left();
Expression *right = better_filter->right();
CompOp comp = better_filter->comp();
if (left->type() == ExprType::VALUE && right->type() == ExprType::FIELD) {
std::swap(left, right);
switch (comp) {
case EQUAL_TO: { comp = EQUAL_TO; } break;
case LESS_EQUAL: { comp = GREAT_THAN; } break;
case NOT_EQUAL: { comp = NOT_EQUAL; } break;
case LESS_THAN: { comp = GREAT_EQUAL; } break;
case GREAT_EQUAL: { comp = LESS_THAN; } break;
case GREAT_THAN: { comp = LESS_EQUAL; } break;
default: {
LOG_WARN("should not happen");
}
}
}
FieldExpr &left_field_expr = *(FieldExpr *)left;
const Field &field = left_field_expr.field();
const Table *table = field.table();
Index *index = table->find_index_by_field(field.field_name());
assert(index != nullptr);
ValueExpr &right_value_expr = *(ValueExpr *)right;
TupleCell value;
right_value_expr.get_tuple_cell(value);
const TupleCell *left_cell = nullptr;
const TupleCell *right_cell = nullptr;
bool left_inclusive = false;
bool right_inclusive = false;
switch (comp) {
case EQUAL_TO: {
left_cell = &value;
right_cell = &value;
left_inclusive = true;
right_inclusive = true;
} break;
case LESS_EQUAL: {
left_cell = nullptr;
left_inclusive = false;
right_cell = &value;
right_inclusive = true;
} break;
case LESS_THAN: {
left_cell = nullptr;
left_inclusive = false;
right_cell = &value;
right_inclusive = false;
} break;
case GREAT_EQUAL: {
left_cell = &value;
left_inclusive = true;
right_cell = nullptr;
right_inclusive = false;
} break;
case GREAT_THAN: {
left_cell = &value;
left_inclusive = false;
right_cell = nullptr;
right_inclusive = false;
} break;
default: {
LOG_WARN("should not happen. comp=%d", comp);
} break;
}
IndexScanOperator *oper = new IndexScanOperator(table, index,
left_cell, left_inclusive, right_cell, right_inclusive);
LOG_INFO("use index for scan: %s in table %s", index->index_meta().name(), table->name());
return oper;
}
RC ExecuteStage::do_select(SQLStageEvent *sql_event)
{
SelectStmt *select_stmt = (SelectStmt *)(sql_event->stmt());
SessionEvent *session_event = sql_event->session_event();
RC rc = RC::SUCCESS;
if (select_stmt->tables().size() != 1) {
LOG_WARN("select more than 1 tables is not supported");
rc = RC::UNIMPLENMENT;
return rc;
}
Operator *scan_oper = try_to_create_index_scan_operator(select_stmt->filter_stmt());
if (nullptr == scan_oper) {
scan_oper = new TableScanOperator(select_stmt->tables()[0]);
}
DEFER([&] () {delete scan_oper;});
PredicateOperator pred_oper(select_stmt->filter_stmt());
pred_oper.add_child(scan_oper);
ProjectOperator project_oper;
project_oper.add_child(&pred_oper);
for (const Field &field : select_stmt->query_fields()) {
project_oper.add_projection(field.table(), field.meta());
}
rc = project_oper.open();
if (rc != RC::SUCCESS) {
LOG_WARN("failed to open operator");
return rc;
}
std::stringstream ss; std::stringstream ss;
if (tuple_sets.size() > 1) { print_tuple_header(ss, project_oper);
// 本次查询了多张表,需要做join操作 while ((rc = project_oper.next()) == RC::SUCCESS) {
} else { // get current record
// 当前只查询一张表,直接返回结果即可 // write to response
tuple_sets.front().print(ss); Tuple * tuple = project_oper.current_tuple();
if (nullptr == tuple) {
rc = RC::INTERNAL;
LOG_WARN("failed to get current record. rc=%s", strrc(rc));
break;
}
tuple_to_string(ss, *tuple);
ss << std::endl;
} }
for (SelectExeNode *&tmp_node : select_nodes) { if (rc != RC::RECORD_EOF) {
delete tmp_node; LOG_WARN("something wrong while iterate operator. rc=%s", strrc(rc));
project_oper.close();
} else {
rc = project_oper.close();
} }
session_event->set_response(ss.str()); session_event->set_response(ss.str());
end_trx_if_need(session, trx, true);
return rc; return rc;
} }
bool match_table(const Selects &selects, const char *table_name_in_condition, const char *table_name_to_match) RC ExecuteStage::do_help(SQLStageEvent *sql_event)
{ {
if (table_name_in_condition != nullptr) { SessionEvent *session_event = sql_event->session_event();
return 0 == strcmp(table_name_in_condition, table_name_to_match); const char *response = "show tables;\n"
"desc `table name`;\n"
"create table `table name` (`column name` `column type`, ...);\n"
"create index `index name` on `table` (`column`);\n"
"insert into `table` values(`value1`,`value2`);\n"
"update `table` set column=value [where `column`=`value`];\n"
"delete from `table` [where `column`=`value`];\n"
"select [ * | `columns` ] from `table`;\n";
session_event->set_response(response);
return RC::SUCCESS;
}
RC ExecuteStage::do_create_table(SQLStageEvent *sql_event)
{
const CreateTable &create_table = sql_event->query()->sstr.create_table;
SessionEvent *session_event = sql_event->session_event();
Db *db = session_event->session()->get_current_db();
RC rc = db->create_table(create_table.relation_name,
create_table.attribute_count, create_table.attributes);
if (rc == RC::SUCCESS) {
session_event->set_response("SUCCESS\n");
} else {
session_event->set_response("FAILURE\n");
}
return rc;
}
RC ExecuteStage::do_create_index(SQLStageEvent *sql_event)
{
SessionEvent *session_event = sql_event->session_event();
Db *db = session_event->session()->get_current_db();
const CreateIndex &create_index = sql_event->query()->sstr.create_index;
Table *table = db->find_table(create_index.relation_name);
if (nullptr == table) {
session_event->set_response("FAILURE\n");
return RC::SCHEMA_TABLE_NOT_EXIST;
} }
return selects.relation_num == 1; RC rc = table->create_index(nullptr, create_index.index_name, create_index.attribute_name);
sql_event->session_event()->set_response(rc == RC::SUCCESS ? "SUCCESS\n" : "FAILURE\n");
return rc;
} }
static RC schema_add_field(Table *table, const char *field_name, TupleSchema &schema) RC ExecuteStage::do_show_tables(SQLStageEvent *sql_event)
{ {
const FieldMeta *field_meta = table->table_meta().field(field_name); SessionEvent *session_event = sql_event->session_event();
if (nullptr == field_meta) { Db *db = session_event->session()->get_current_db();
LOG_WARN("No such field. %s.%s", table->name(), field_name); std::vector<std::string> all_tables;
return RC::SCHEMA_FIELD_MISSING; db->all_tables(all_tables);
if (all_tables.empty()) {
session_event->set_response("No table\n");
} else {
std::stringstream ss;
for (const auto &table : all_tables) {
ss << table << std::endl;
}
session_event->set_response(ss.str().c_str());
} }
return RC::SUCCESS;
}
schema.add_if_not_exists(field_meta->type(), table->name(), field_meta->name()); RC ExecuteStage::do_desc_table(SQLStageEvent *sql_event)
{
Query *query = sql_event->query();
Db *db = sql_event->session_event()->session()->get_current_db();
const char *table_name = query->sstr.desc_table.relation_name;
Table *table = db->find_table(table_name);
std::stringstream ss;
if (table != nullptr) {
table->table_meta().desc(ss);
} else {
ss << "No such table: " << table_name << std::endl;
}
sql_event->session_event()->set_response(ss.str().c_str());
return RC::SUCCESS; return RC::SUCCESS;
} }
// 把所有的表和只跟这张表关联的condition都拿出来,生成最底层的select 执行节点 RC ExecuteStage::do_insert(SQLStageEvent *sql_event)
RC create_selection_executor(
Trx *trx, const Selects &selects, const char *db, const char *table_name, SelectExeNode &select_node)
{ {
// 列出跟这张表关联的Attr Stmt *stmt = sql_event->stmt();
TupleSchema schema; SessionEvent *session_event = sql_event->session_event();
Table *table = DefaultHandler::get_default().find_table(db, table_name);
if (nullptr == table) { if (stmt == nullptr) {
LOG_WARN("No such table [%s] in db [%s]", table_name, db); LOG_WARN("cannot find statement");
return RC::SCHEMA_TABLE_NOT_EXIST; return RC::GENERIC_ERROR;
} }
for (int i = selects.attr_num - 1; i >= 0; i--) { InsertStmt *insert_stmt = (InsertStmt *)stmt;
const RelAttr &attr = selects.attributes[i];
if (nullptr == attr.relation_name || 0 == strcmp(table_name, attr.relation_name)) { Table *table = insert_stmt->table();
if (0 == strcmp("*", attr.attribute_name)) { RC rc = table->insert_record(nullptr, insert_stmt->value_amount(), insert_stmt->values());
// 列出这张表所有字段 if (rc == RC::SUCCESS) {
TupleSchema::from_table(table, schema); session_event->set_response("SUCCESS\n");
break; // 没有校验,给出* 之后,再写字段的错误 } else {
} else { session_event->set_response("FAILURE\n");
// 列出这张表相关字段
RC rc = schema_add_field(table, attr.attribute_name, schema);
if (rc != RC::SUCCESS) {
return rc;
}
}
}
} }
return rc;
}
// 找出仅与此表相关的过滤条件, 或者都是值的过滤条件 RC ExecuteStage::do_delete(SQLStageEvent *sql_event)
std::vector<DefaultConditionFilter *> condition_filters; {
for (size_t i = 0; i < selects.condition_num; i++) { Stmt *stmt = sql_event->stmt();
const Condition &condition = selects.conditions[i]; SessionEvent *session_event = sql_event->session_event();
if ((condition.left_is_attr == 0 && condition.right_is_attr == 0) || // 两边都是值
(condition.left_is_attr == 1 && condition.right_is_attr == 0 && if (stmt == nullptr) {
match_table(selects, condition.left_attr.relation_name, table_name)) || // 左边是属性右边是值 LOG_WARN("cannot find statement");
(condition.left_is_attr == 0 && condition.right_is_attr == 1 && return RC::GENERIC_ERROR;
match_table(selects, condition.right_attr.relation_name, table_name)) || // 左边是值,右边是属性名
(condition.left_is_attr == 1 && condition.right_is_attr == 1 &&
match_table(selects, condition.left_attr.relation_name, table_name) &&
match_table(selects, condition.right_attr.relation_name, table_name)) // 左右都是属性名,并且表名都符合
) {
DefaultConditionFilter *condition_filter = new DefaultConditionFilter();
RC rc = condition_filter->init(*table, condition);
if (rc != RC::SUCCESS) {
delete condition_filter;
for (DefaultConditionFilter *&filter : condition_filters) {
delete filter;
}
return rc;
}
condition_filters.push_back(condition_filter);
}
} }
return select_node.init(trx, table, std::move(schema), std::move(condition_filters)); DeleteStmt *delete_stmt = (DeleteStmt *)stmt;
TableScanOperator scan_oper(delete_stmt->table());
PredicateOperator pred_oper(delete_stmt->filter_stmt());
pred_oper.add_child(&scan_oper);
DeleteOperator delete_oper(delete_stmt);
delete_oper.add_child(&pred_oper);
RC rc = delete_oper.open();
if (rc != RC::SUCCESS) {
session_event->set_response("FAILURE\n");
} else {
session_event->set_response("SUCCESS\n");
}
return rc;
} }
...@@ -19,7 +19,9 @@ See the Mulan PSL v2 for more details. */ ...@@ -19,7 +19,9 @@ See the Mulan PSL v2 for more details. */
#include "sql/parser/parse.h" #include "sql/parser/parse.h"
#include "rc.h" #include "rc.h"
class SQLStageEvent;
class SessionEvent; class SessionEvent;
class SelectStmt;
class ExecuteStage : public common::Stage { class ExecuteStage : public common::Stage {
public: public:
...@@ -37,7 +39,14 @@ protected: ...@@ -37,7 +39,14 @@ protected:
void callback_event(common::StageEvent *event, common::CallbackContext *context) override; void callback_event(common::StageEvent *event, common::CallbackContext *context) override;
void handle_request(common::StageEvent *event); 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: protected:
private: 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. ...@@ -9,21 +9,18 @@ MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */ 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 "sql/expr/tuple.h"
#include "event/sql_event.h"
ExecutionPlanEvent::ExecutionPlanEvent(SQLStageEvent *sql_event, Query *sqls) : sql_event_(sql_event), sqls_(sqls)
{} RC FieldExpr::get_value(const Tuple &tuple, TupleCell &cell) const
ExecutionPlanEvent::~ExecutionPlanEvent()
{ {
sql_event_ = nullptr; return tuple.find_cell(field_, cell);
// if (sql_event_) { }
// sql_event_->doneImmediate();
// }
query_destroy(sqls_); RC ValueExpr::get_value(const Tuple &tuple, TupleCell & cell) const
sqls_ = nullptr; {
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. ...@@ -9,46 +9,55 @@ MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */ 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 "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) RC DeleteOperator::open()
{}
SelectExeNode::~SelectExeNode()
{ {
for (DefaultConditionFilter *&filter : condition_filters_) { if (children_.size() != 1) {
delete filter; LOG_WARN("delete operator must has 1 child");
return RC::INTERNAL;
} }
condition_filters_.clear();
}
RC SelectExeNode::init( Operator *child = children_[0];
Trx *trx, Table *table, TupleSchema &&tuple_schema, std::vector<DefaultConditionFilter *> &&condition_filters) RC rc = child->open();
{ if (rc != RC::SUCCESS) {
trx_ = trx; LOG_WARN("failed to open child operator: %s", strrc(rc));
table_ = table; return rc;
tuple_schema_ = tuple_schema; }
condition_filters_ = std::move(condition_filters);
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; return RC::SUCCESS;
} }
void record_reader(const char *data, void *context) RC DeleteOperator::next()
{ {
TupleRecordConverter *converter = (TupleRecordConverter *)context; return RC::RECORD_EOF;
converter->add_record(data);
} }
RC SelectExeNode::execute(TupleSet &tuple_set)
RC DeleteOperator::close()
{ {
CompositeConditionFilter condition_filter; children_[0]->close();
condition_filter.init((const ConditionFilter **)condition_filters_.data(), condition_filters_.size()); return RC::SUCCESS;
}
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
/* 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() ...@@ -65,7 +65,7 @@ bool OptimizeStage::initialize()
LOG_TRACE("Enter"); LOG_TRACE("Enter");
std::list<Stage *>::iterator stgp = next_stage_list_.begin(); std::list<Stage *>::iterator stgp = next_stage_list_.begin();
execute_stage = *(stgp++); execute_stage_ = *(stgp++);
LOG_TRACE("Exit"); LOG_TRACE("Exit");
return true; return true;
...@@ -84,7 +84,7 @@ void OptimizeStage::handle_event(StageEvent *event) ...@@ -84,7 +84,7 @@ void OptimizeStage::handle_event(StageEvent *event)
LOG_TRACE("Enter\n"); LOG_TRACE("Enter\n");
// optimize sql plan, here just pass the event to the next stage // 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"); LOG_TRACE("Exit\n");
return; return;
...@@ -93,7 +93,6 @@ void OptimizeStage::handle_event(StageEvent *event) ...@@ -93,7 +93,6 @@ void OptimizeStage::handle_event(StageEvent *event)
void OptimizeStage::callback_event(StageEvent *event, CallbackContext *context) void OptimizeStage::callback_event(StageEvent *event, CallbackContext *context)
{ {
LOG_TRACE("Enter\n"); LOG_TRACE("Enter\n");
LOG_TRACE("Exit\n"); LOG_TRACE("Exit\n");
return; return;
} }
...@@ -34,7 +34,7 @@ protected: ...@@ -34,7 +34,7 @@ protected:
protected: protected:
private: private:
Stage *execute_stage = nullptr; Stage *execute_stage_ = nullptr;
}; };
#endif //__OBSERVER_SQL_OPTIMIZE_STAGE_H__ #endif //__OBSERVER_SQL_OPTIMIZE_STAGE_H__
...@@ -40,7 +40,13 @@ typedef enum { ...@@ -40,7 +40,13 @@ typedef enum {
} CompOp; } CompOp;
//属性值类型 //属性值类型
typedef enum { UNDEFINED, CHARS, INTS, FLOATS } AttrType; typedef enum
{
UNDEFINED,
CHARS,
INTS,
FLOATS
} AttrType;
//属性值 //属性值
typedef struct _Value { typedef struct _Value {
...@@ -238,4 +244,4 @@ void query_destroy(Query *query); // reset and delete ...@@ -238,4 +244,4 @@ void query_destroy(Query *query); // reset and delete
} }
#endif // __cplusplus #endif // __cplusplus
#endif // __OBSERVER_SQL_PARSER_PARSE_DEFS_H__ #endif // __OBSERVER_SQL_PARSER_PARSE_DEFS_H__
\ No newline at end of file
...@@ -25,7 +25,6 @@ See the Mulan PSL v2 for more details. */ ...@@ -25,7 +25,6 @@ See the Mulan PSL v2 for more details. */
#include "event/session_event.h" #include "event/session_event.h"
#include "event/sql_event.h" #include "event/sql_event.h"
#include "sql/parser/parse.h" #include "sql/parser/parse.h"
#include "event/execution_plan_event.h"
using namespace common; using namespace common;
...@@ -69,7 +68,8 @@ bool ParseStage::initialize() ...@@ -69,7 +68,8 @@ bool ParseStage::initialize()
LOG_TRACE("Enter"); LOG_TRACE("Enter");
std::list<Stage *>::iterator stgp = next_stage_list_.begin(); std::list<Stage *>::iterator stgp = next_stage_list_.begin();
optimize_stage_ = *(stgp++); // optimize_stage_ = *(stgp++);
resolve_stage_ = *(stgp++);
LOG_TRACE("Exit"); LOG_TRACE("Exit");
return true; return true;
...@@ -87,10 +87,9 @@ void ParseStage::handle_event(StageEvent *event) ...@@ -87,10 +87,9 @@ void ParseStage::handle_event(StageEvent *event)
{ {
LOG_TRACE("Enter\n"); LOG_TRACE("Enter\n");
StageEvent *new_event = handle_request(event); RC rc = handle_request(event);
if (nullptr == new_event) { if (RC::SUCCESS != rc) {
callback_event(event, nullptr); callback_event(event, nullptr);
event->done_immediate();
return; return;
} }
...@@ -98,11 +97,12 @@ void ParseStage::handle_event(StageEvent *event) ...@@ -98,11 +97,12 @@ void ParseStage::handle_event(StageEvent *event)
if (cb == nullptr) { if (cb == nullptr) {
LOG_ERROR("Failed to new callback for SQLStageEvent"); LOG_ERROR("Failed to new callback for SQLStageEvent");
callback_event(event, nullptr); callback_event(event, nullptr);
event->done_immediate();
return; return;
} }
event->push_callback(cb); event->push_callback(cb);
optimize_stage_->handle_event(new_event); resolve_stage_->handle_event(event);
event->done_immediate();
LOG_TRACE("Exit\n"); LOG_TRACE("Exit\n");
return; return;
...@@ -113,31 +113,30 @@ void ParseStage::callback_event(StageEvent *event, CallbackContext *context) ...@@ -113,31 +113,30 @@ void ParseStage::callback_event(StageEvent *event, CallbackContext *context)
LOG_TRACE("Enter\n"); LOG_TRACE("Enter\n");
SQLStageEvent *sql_event = static_cast<SQLStageEvent *>(event); SQLStageEvent *sql_event = static_cast<SQLStageEvent *>(event);
sql_event->session_event()->done_immediate(); sql_event->session_event()->done_immediate();
sql_event->done_immediate();
LOG_TRACE("Exit\n"); LOG_TRACE("Exit\n");
return; return;
} }
StageEvent *ParseStage::handle_request(StageEvent *event) RC ParseStage::handle_request(StageEvent *event)
{ {
SQLStageEvent *sql_event = static_cast<SQLStageEvent *>(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(); Query *query_result = query_create();
if (nullptr == result) { if (nullptr == query_result) {
LOG_ERROR("Failed to create query."); 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) { if (ret != RC::SUCCESS) {
// set error information to event // set error information to event
const char *error = result->sstr.errors != nullptr ? result->sstr.errors : "Unknown error"; sql_event->session_event()->set_response("Failed to parse sql\n");
char response[256]; query_destroy(query_result);
snprintf(response, sizeof(response), "Failed to parse sql: %s, error msg: %s\n", sql.c_str(), error); return RC::INTERNAL;
sql_event->session_event()->set_response(response);
query_destroy(result);
return nullptr;
} }
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. */ ...@@ -16,6 +16,7 @@ See the Mulan PSL v2 for more details. */
#define __OBSERVER_SQL_PARSE_STAGE_H__ #define __OBSERVER_SQL_PARSE_STAGE_H__
#include "common/seda/stage.h" #include "common/seda/stage.h"
#include "rc.h"
class ParseStage : public common::Stage { class ParseStage : public common::Stage {
public: public:
...@@ -33,10 +34,11 @@ protected: ...@@ -33,10 +34,11 @@ protected:
void callback_event(common::StageEvent *event, common::CallbackContext *context); void callback_event(common::StageEvent *event, common::CallbackContext *context);
protected: protected:
common::StageEvent *handle_request(common::StageEvent *event); RC handle_request(common::StageEvent *event);
private: private:
Stage *optimize_stage_ = nullptr; Stage *optimize_stage_ = nullptr;
Stage *resolve_stage_ = nullptr;
}; };
#endif //__OBSERVER_SQL_PARSE_STAGE_H__ #endif //__OBSERVER_SQL_PARSE_STAGE_H__
...@@ -23,6 +23,9 @@ See the Mulan PSL v2 for more details. */ ...@@ -23,6 +23,9 @@ See the Mulan PSL v2 for more details. */
#include "common/log/log.h" #include "common/log/log.h"
#include "common/seda/timer_stage.h" #include "common/seda/timer_stage.h"
#include "event/sql_event.h" #include "event/sql_event.h"
#include "event/session_event.h"
#include "session/session.h"
#include "sql/stmt/stmt.h"
using namespace common; using namespace common;
...@@ -66,7 +69,7 @@ bool ResolveStage::initialize() ...@@ -66,7 +69,7 @@ bool ResolveStage::initialize()
LOG_TRACE("Enter"); LOG_TRACE("Enter");
std::list<Stage *>::iterator stgp = next_stage_list_.begin(); std::list<Stage *>::iterator stgp = next_stage_list_.begin();
query_cache_stage = *(stgp++); query_cache_stage_ = *(stgp++);
LOG_TRACE("Exit"); LOG_TRACE("Exit");
return true; return true;
...@@ -85,9 +88,31 @@ void ResolveStage::handle_event(StageEvent *event) ...@@ -85,9 +88,31 @@ void ResolveStage::handle_event(StageEvent *event)
LOG_TRACE("Enter\n"); LOG_TRACE("Enter\n");
SQLStageEvent *sql_event = static_cast<SQLStageEvent *>(event); 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"); LOG_TRACE("Exit\n");
return; return;
......
...@@ -34,7 +34,7 @@ protected: ...@@ -34,7 +34,7 @@ protected:
protected: protected:
private: private:
Stage *query_cache_stage = nullptr; Stage *query_cache_stage_ = nullptr;
}; };
#endif //__OBSERVER_SQL_RESOLVE_STAGE_H__ #endif //__OBSERVER_SQL_RESOLVE_STAGE_H__
...@@ -65,8 +65,8 @@ bool PlanCacheStage::initialize() ...@@ -65,8 +65,8 @@ bool PlanCacheStage::initialize()
LOG_TRACE("Enter"); LOG_TRACE("Enter");
std::list<Stage *>::iterator stgp = next_stage_list_.begin(); std::list<Stage *>::iterator stgp = next_stage_list_.begin();
execute_stage = *(stgp++); // execute_stage = *(stgp++);
parse_stage = *(stgp++); parse_stage_ = *(stgp++);
LOG_TRACE("Exit"); LOG_TRACE("Exit");
return true; return true;
...@@ -96,7 +96,7 @@ void PlanCacheStage::handle_event(StageEvent *event) ...@@ -96,7 +96,7 @@ void PlanCacheStage::handle_event(StageEvent *event)
event->push_callback(cb); event->push_callback(cb);
*/ */
// do nothing here, pass the event to the next stage // do nothing here, pass the event to the next stage
parse_stage->handle_event(event); parse_stage_->handle_event(event);
LOG_TRACE("Exit\n"); LOG_TRACE("Exit\n");
return; return;
......
...@@ -34,8 +34,7 @@ protected: ...@@ -34,8 +34,7 @@ protected:
protected: protected:
private: private:
Stage *parse_stage = nullptr; Stage *parse_stage_ = nullptr;
Stage *execute_stage = nullptr;
}; };
#endif //__OBSERVER_SQL_PLAN_CACHE_STAGE_H__ #endif //__OBSERVER_SQL_PLAN_CACHE_STAGE_H__
...@@ -65,7 +65,7 @@ bool QueryCacheStage::initialize() ...@@ -65,7 +65,7 @@ bool QueryCacheStage::initialize()
LOG_TRACE("Enter"); LOG_TRACE("Enter");
std::list<Stage *>::iterator stgp = next_stage_list_.begin(); std::list<Stage *>::iterator stgp = next_stage_list_.begin();
plan_cache_stage = *(stgp++); optimize_stage_ = *(stgp++);
LOG_TRACE("Exit"); LOG_TRACE("Exit");
return true; return true;
...@@ -83,19 +83,7 @@ void QueryCacheStage::handle_event(StageEvent *event) ...@@ -83,19 +83,7 @@ void QueryCacheStage::handle_event(StageEvent *event)
{ {
LOG_TRACE("Enter\n"); LOG_TRACE("Enter\n");
// Add callback to update query cache optimize_stage_->handle_event(event);
/*
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);
LOG_TRACE("Exit\n"); LOG_TRACE("Exit\n");
return; return;
...@@ -104,10 +92,6 @@ void QueryCacheStage::handle_event(StageEvent *event) ...@@ -104,10 +92,6 @@ void QueryCacheStage::handle_event(StageEvent *event)
void QueryCacheStage::callback_event(StageEvent *event, CallbackContext *context) void QueryCacheStage::callback_event(StageEvent *event, CallbackContext *context)
{ {
LOG_TRACE("Enter\n"); LOG_TRACE("Enter\n");
// update data to query cache here
// event->done_immediate();
LOG_TRACE("Exit\n"); LOG_TRACE("Exit\n");
return; return;
} }
...@@ -34,7 +34,7 @@ protected: ...@@ -34,7 +34,7 @@ protected:
protected: protected:
private: private:
Stage *plan_cache_stage = nullptr; Stage *optimize_stage_ = nullptr;
}; };
#endif //__OBSERVER_SQL_QUERY_CACHE_STAGE_H__ #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. ...@@ -9,42 +9,41 @@ MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */ 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_ #pragma once
#define __OBSERVER_SQL_EXECUTOR_EXECUTION_NODE_H_
#include <vector> #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 Table;
class Trx;
class ExecutionNode { class SelectStmt : public Stmt
{
public: 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: public:
SelectExeNode(); static RC create(Db *db, const Selects &select_sql, Stmt *&stmt);
virtual ~SelectExeNode();
RC init( public:
Trx *trx, Table *table, TupleSchema &&tuple_schema, std::vector<DefaultConditionFilter *> &&condition_filters); const std::vector<Table *> &tables() const { return tables_; }
const std::vector<Field> &query_fields() const { return query_fields_; }
RC execute(TupleSet &tuple_set) override; FilterStmt *filter_stmt() const { return filter_stmt_; }
private: private:
Trx *trx_ = nullptr; std::vector<Field> query_fields_;
Table *table_; std::vector<Table *> tables_;
TupleSchema tuple_schema_; FilterStmt *filter_stmt_ = nullptr;
std::vector<DefaultConditionFilter *> condition_filters_;
}; };
#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. ...@@ -9,20 +9,18 @@ MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */ 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 "sql/stmt/update_stmt.h"
#include "event/execution_plan_event.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; // TODO
// if (exe_event_ != nullptr) { stmt = nullptr;
// ExecutionPlanEvent *exe_event = exe_event_; return RC::INTERNAL;
// exe_event->doneImmediate(); }
// }
}
\ 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 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 ...@@ -129,13 +129,13 @@ bool DefaultConditionFilter::filter(const Record &rec) const
char *right_value = nullptr; char *right_value = nullptr;
if (left_.is_attr) { // value if (left_.is_attr) { // value
left_value = (char *)(rec.data + left_.attr_offset); left_value = (char *)(rec.data() + left_.attr_offset);
} else { } else {
left_value = (char *)left_.value; left_value = (char *)left_.value;
} }
if (right_.is_attr) { if (right_.is_attr) {
right_value = (char *)(rec.data + right_.attr_offset); right_value = (char *)(rec.data() + right_.attr_offset);
} else { } else {
right_value = (char *)right_.value; right_value = (char *)right_.value;
} }
......
...@@ -18,7 +18,7 @@ See the Mulan PSL v2 for more details. */ ...@@ -18,7 +18,7 @@ See the Mulan PSL v2 for more details. */
#include "rc.h" #include "rc.h"
#include "sql/parser/parse.h" #include "sql/parser/parse.h"
struct Record; class Record;
class Table; class Table;
struct ConDesc { struct ConDesc {
...@@ -101,4 +101,4 @@ private: ...@@ -101,4 +101,4 @@ private:
bool memory_owner_ = false; // filters_的内存是否由自己来控制 bool memory_owner_ = false; // filters_的内存是否由自己来控制
}; };
#endif // __OBSERVER_STORAGE_COMMON_CONDITION_FILTER_H_ #endif // __OBSERVER_STORAGE_COMMON_CONDITION_FILTER_H_
\ 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 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() ...@@ -67,14 +67,13 @@ bool RecordPageIterator::has_next()
RC RecordPageIterator::next(Record &record) RC RecordPageIterator::next(Record &record)
{ {
record.rid.page_num = page_num_; record.set_rid(page_num_, next_slot_num_);
record.rid.slot_num = next_slot_num_; record.set_data(record_page_handler_->get_record_data(record.rid().slot_num));
record.data = record_page_handler_->get_record_data(record.rid.slot_num);
if (next_slot_num_ >= 0) { if (next_slot_num_ >= 0) {
next_slot_num_ = bitmap_.next_setted_bit(next_slot_num_ + 1); 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) ...@@ -170,21 +169,21 @@ RC RecordPageHandler::insert_record(const char *data, RID *rid)
RC RecordPageHandler::update_record(const Record *rec) 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.", 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; return RC::INVALID_ARGUMENT;
} }
Bitmap bitmap(bitmap_, page_header_->record_capacity); 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.", 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; return RC::RECORD_RECORD_NOT_EXIST;
} else { } else {
char *record_data = get_record_data(rec->rid.slot_num); char *record_data = get_record_data(rec->rid().slot_num);
memcpy(record_data, rec->data, page_header_->record_real_size); memcpy(record_data, rec->data(), page_header_->record_real_size);
bitmap.set_bit(rec->rid.slot_num); bitmap.set_bit(rec->rid().slot_num);
frame_->mark_dirty(); 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); // 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; return RC::SUCCESS;
...@@ -234,8 +233,8 @@ RC RecordPageHandler::get_record(const RID *rid, Record *rec) ...@@ -234,8 +233,8 @@ RC RecordPageHandler::get_record(const RID *rid, Record *rec)
return RC::RECORD_RECORD_NOT_EXIST; return RC::RECORD_RECORD_NOT_EXIST;
} }
rec->rid = *rid; rec->set_rid(*rid);
rec->data = get_record_data(rid->slot_num); rec->set_data(get_record_data(rid->slot_num));
return RC::SUCCESS; return RC::SUCCESS;
} }
...@@ -328,8 +327,8 @@ RC RecordFileHandler::update_record(const Record *rec) ...@@ -328,8 +327,8 @@ RC RecordFileHandler::update_record(const Record *rec)
{ {
RC ret; RC ret;
RecordPageHandler page_handler; RecordPageHandler page_handler;
if ((ret = page_handler.init(*disk_buffer_pool_, rec->rid.page_num)) != RC::SUCCESS) { 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); LOG_ERROR("Failed to init record page handler.page number=%d", rec->rid().page_num);
return ret; return ret;
} }
...@@ -412,7 +411,7 @@ RC RecordFileScanner::fetch_next_record() ...@@ -412,7 +411,7 @@ RC RecordFileScanner::fetch_next_record()
return rc; return rc;
} }
} }
next_record_.rid.slot_num = -1; next_record_.rid().slot_num = -1;
return RC::RECORD_EOF; return RC::RECORD_EOF;
} }
...@@ -430,7 +429,7 @@ RC RecordFileScanner::fetch_next_record_in_page() ...@@ -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; return RC::RECORD_EOF;
} }
...@@ -449,7 +448,7 @@ RC RecordFileScanner::close_scan() ...@@ -449,7 +448,7 @@ RC RecordFileScanner::close_scan()
bool RecordFileScanner::has_next() bool RecordFileScanner::has_next()
{ {
return next_record_.rid.slot_num != -1; return next_record_.rid().slot_num != -1;
} }
RC RecordFileScanner::next(Record &record) RC RecordFileScanner::next(Record &record)
......
...@@ -17,10 +17,9 @@ See the Mulan PSL v2 for more details. */ ...@@ -17,10 +17,9 @@ See the Mulan PSL v2 for more details. */
#include <sstream> #include <sstream>
#include <limits> #include <limits>
#include "storage/default/disk_buffer_pool.h" #include "storage/default/disk_buffer_pool.h"
#include "storage/common/record.h"
#include "common/lang/bitmap.h" #include "common/lang/bitmap.h"
typedef int32_t SlotNum;
class ConditionFilter; class ConditionFilter;
struct PageHeader { struct PageHeader {
...@@ -31,56 +30,6 @@ struct PageHeader { ...@@ -31,56 +30,6 @@ struct PageHeader {
int32_t first_record_offset; // 第一条记录的偏移量 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 { class RidDigest {
public: public:
...@@ -90,12 +39,6 @@ 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 RecordPageHandler;
class RecordPageIterator class RecordPageIterator
{ {
......
...@@ -202,7 +202,7 @@ RC Table::rollback_insert(Trx *trx, const RID &rid) ...@@ -202,7 +202,7 @@ RC Table::rollback_insert(Trx *trx, const RID &rid)
} }
// remove all indexes // 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) { if (rc != RC::SUCCESS) {
LOG_ERROR("Failed to delete indexes of record(rid=%d.%d) while rollback insert, rc=%d:%s", LOG_ERROR("Failed to delete indexes of record(rid=%d.%d) while rollback insert, rc=%d:%s",
rid.page_num, rid.page_num,
...@@ -223,7 +223,7 @@ RC Table::insert_record(Trx *trx, Record *record) ...@@ -223,7 +223,7 @@ RC Table::insert_record(Trx *trx, Record *record)
if (trx != nullptr) { if (trx != nullptr) {
trx->init_trx_info(this, *record); 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) { if (rc != RC::SUCCESS) {
LOG_ERROR("Insert record failed. table name=%s, rc=%d:%s", table_meta_.name(), rc, strrc(rc)); LOG_ERROR("Insert record failed. table name=%s, rc=%d:%s", table_meta_.name(), rc, strrc(rc));
return rc; return rc;
...@@ -234,7 +234,7 @@ RC Table::insert_record(Trx *trx, Record *record) ...@@ -234,7 +234,7 @@ RC Table::insert_record(Trx *trx, Record *record)
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_ERROR("Failed to log operation(insertion) to trx"); 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) { if (rc2 != RC::SUCCESS) {
LOG_ERROR("Failed to rollback record data when insert index entries failed. table name=%s, rc=%d:%s", LOG_ERROR("Failed to rollback record data when insert index entries failed. table name=%s, rc=%d:%s",
name(), name(),
...@@ -245,16 +245,16 @@ RC Table::insert_record(Trx *trx, Record *record) ...@@ -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) { 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) { if (rc2 != RC::SUCCESS) {
LOG_ERROR("Failed to rollback index data when insert index entries failed. table name=%s, rc=%d:%s", LOG_ERROR("Failed to rollback index data when insert index entries failed. table name=%s, rc=%d:%s",
name(), name(),
rc2, rc2,
strrc(rc2)); strrc(rc2));
} }
rc2 = record_handler_->delete_record(&record->rid); rc2 = record_handler_->delete_record(&record->rid());
if (rc2 != RC::SUCCESS) { if (rc2 != RC::SUCCESS) {
LOG_PANIC("Failed to rollback record data when insert index entries failed. table name=%s, rc=%d:%s", LOG_PANIC("Failed to rollback record data when insert index entries failed. table name=%s, rc=%d:%s",
name(), name(),
...@@ -280,7 +280,7 @@ RC Table::insert_record(Trx *trx, int value_num, const Value *values) ...@@ -280,7 +280,7 @@ RC Table::insert_record(Trx *trx, int value_num, const Value *values)
} }
Record record; Record record;
record.data = record_data; record.set_data(record_data);
// record.valid = true; // record.valid = true;
rc = insert_record(trx, &record); rc = insert_record(trx, &record);
delete[] record_data; delete[] record_data;
...@@ -357,6 +357,15 @@ RC Table::init_record_handler(const char *base_dir) ...@@ -357,6 +357,15 @@ RC Table::init_record_handler(const char *base_dir)
return rc; 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暴露出去,封装一下 * 为了不把Record暴露出去,封装一下
*/ */
...@@ -368,7 +377,7 @@ public: ...@@ -368,7 +377,7 @@ public:
void consume(const Record *record) void consume(const Record *record)
{ {
record_reader_(record->data, context_); record_reader_(record->data(), context_);
} }
private: private:
...@@ -383,15 +392,16 @@ static RC scan_record_reader_adapter(Record *record, void *context) ...@@ -383,15 +392,16 @@ static RC scan_record_reader_adapter(Record *record, void *context)
return RC::SUCCESS; return RC::SUCCESS;
} }
RC Table::scan_record( RC Table::scan_record(Trx *trx, ConditionFilter *filter,
Trx *trx, ConditionFilter *filter, int limit, void *context, void (*record_reader)(const char *data, void *context)) int limit, void *context,
void (*record_reader)(const char *data, void *context))
{ {
RecordReaderScanAdapter adapter(record_reader, context); RecordReaderScanAdapter adapter(record_reader, context);
return scan_record(trx, filter, limit, (void *)&adapter, scan_record_reader_adapter); 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 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) { if (nullptr == record_reader) {
return RC::INVALID_ARGUMENT; return RC::INVALID_ARGUMENT;
...@@ -439,8 +449,9 @@ RC Table::scan_record(Trx *trx, ConditionFilter *filter, int limit, void *contex ...@@ -439,8 +449,9 @@ RC Table::scan_record(Trx *trx, ConditionFilter *filter, int limit, void *contex
return rc; return rc;
} }
RC Table::scan_record_by_index(Trx *trx, IndexScanner *scanner, ConditionFilter *filter, int limit, void *context, RC Table::scan_record_by_index(Trx *trx, IndexScanner *scanner, ConditionFilter *filter,
RC (*record_reader)(Record *, void *)) int limit, void *context,
RC (*record_reader)(Record *, void *))
{ {
RC rc = RC::SUCCESS; RC rc = RC::SUCCESS;
RID rid; RID rid;
...@@ -485,7 +496,7 @@ public: ...@@ -485,7 +496,7 @@ public:
RC insert_index(const Record *record) RC insert_index(const Record *record)
{ {
return index_->insert_entry(record->data, &record->rid); return index_->insert_entry(record->data(), &record->rid());
} }
private: private:
...@@ -506,9 +517,7 @@ RC Table::create_index(Trx *trx, const char *index_name, const char *attribute_n ...@@ -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))) { 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", LOG_INFO("Invalid input arguments, table name is %s, index %s exist or attribute %s exist index",
name(), name(), index_name, attribute_name);
index_name,
attribute_name);
return RC::SCHEMA_INDEX_EXIST; return RC::SCHEMA_INDEX_EXIST;
} }
...@@ -521,7 +530,8 @@ RC Table::create_index(Trx *trx, const char *index_name, const char *attribute_n ...@@ -521,7 +530,8 @@ RC Table::create_index(Trx *trx, const char *index_name, const char *attribute_n
IndexMeta new_index_meta; IndexMeta new_index_meta;
RC rc = new_index_meta.init(index_name, *field_meta); RC rc = new_index_meta.init(index_name, *field_meta);
if (rc != RC::SUCCESS) { 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; return rc;
} }
...@@ -642,15 +652,12 @@ RC Table::delete_record(Trx *trx, Record *record) ...@@ -642,15 +652,12 @@ RC Table::delete_record(Trx *trx, Record *record)
if (trx != nullptr) { if (trx != nullptr) {
rc = trx->delete_record(this, record); rc = trx->delete_record(this, record);
} else { } 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) { if (rc != RC::SUCCESS) {
LOG_ERROR("Failed to delete indexes of record (rid=%d.%d). rc=%d:%s", LOG_ERROR("Failed to delete indexes of record (rid=%d.%d). rc=%d:%s",
record->rid.page_num, record->rid().page_num, record->rid().slot_num, rc, strrc(rc));
record->rid.slot_num,
rc,
strrc(rc));
} else { } else {
rc = record_handler_->delete_record(&record->rid); rc = record_handler_->delete_record(&record->rid());
} }
} }
return rc; return rc;
...@@ -664,13 +671,10 @@ RC Table::commit_delete(Trx *trx, const RID &rid) ...@@ -664,13 +671,10 @@ RC Table::commit_delete(Trx *trx, const RID &rid)
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
return rc; 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) { if (rc != RC::SUCCESS) {
LOG_ERROR("Failed to delete indexes of record(rid=%d.%d). rc=%d:%s", LOG_ERROR("Failed to delete indexes of record(rid=%d.%d). rc=%d:%s",
rid.page_num, rid.page_num, rid.slot_num, rc, strrc(rc)); // panic?
rid.slot_num,
rc,
strrc(rc)); // panic?
} }
rc = record_handler_->delete_record(&rid); rc = record_handler_->delete_record(&rid);
...@@ -728,6 +732,15 @@ Index *Table::find_index(const char *index_name) const ...@@ -728,6 +732,15 @@ Index *Table::find_index(const char *index_name) const
} }
return nullptr; 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) IndexScanner *Table::find_index_for_scan(const DefaultConditionFilter &filter)
{ {
...@@ -836,10 +849,7 @@ RC Table::sync() ...@@ -836,10 +849,7 @@ RC Table::sync()
rc = index->sync(); rc = index->sync();
if (rc != RC::SUCCESS) { if (rc != RC::SUCCESS) {
LOG_ERROR("Failed to flush index's pages. table=%s, index=%s, rc=%d:%s", LOG_ERROR("Failed to flush index's pages. table=%s, index=%s, rc=%d:%s",
name(), name(), index->index_meta().name(), rc, strrc(rc));
index->index_meta().name(),
rc,
strrc(rc));
return rc; return rc;
} }
} }
......
...@@ -17,12 +17,13 @@ See the Mulan PSL v2 for more details. */ ...@@ -17,12 +17,13 @@ See the Mulan PSL v2 for more details. */
#include "storage/common/table_meta.h" #include "storage/common/table_meta.h"
struct RID;
class Record;
class DiskBufferPool; class DiskBufferPool;
class RecordFileHandler; class RecordFileHandler;
class RecordFileScanner;
class ConditionFilter; class ConditionFilter;
class DefaultConditionFilter; class DefaultConditionFilter;
struct Record;
struct RID;
class Index; class Index;
class IndexScanner; class IndexScanner;
class RecordDeleter; class RecordDeleter;
...@@ -54,12 +55,20 @@ public: ...@@ -54,12 +55,20 @@ public:
RC update_record(Trx *trx, const char *attribute_name, const Value *value, int condition_num, RC update_record(Trx *trx, const char *attribute_name, const Value *value, int condition_num,
const Condition conditions[], int *updated_count); const Condition conditions[], int *updated_count);
RC delete_record(Trx *trx, ConditionFilter *filter, int *deleted_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, RC scan_record(Trx *trx, ConditionFilter *filter, int limit, void *context,
void (*record_reader)(const char *data, void *context)); void (*record_reader)(const char *data, void *context));
RC create_index(Trx *trx, const char *index_name, const char *attribute_name); 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: public:
const char *name() const; const char *name() const;
...@@ -82,7 +91,6 @@ private: ...@@ -82,7 +91,6 @@ private:
IndexScanner *find_index_for_scan(const DefaultConditionFilter &filter); IndexScanner *find_index_for_scan(const DefaultConditionFilter &filter);
RC insert_record(Trx *trx, Record *record); RC insert_record(Trx *trx, Record *record);
RC delete_record(Trx *trx, Record *record);
private: private:
friend class RecordUpdater; friend class RecordUpdater;
...@@ -95,8 +103,9 @@ private: ...@@ -95,8 +103,9 @@ private:
RC init_record_handler(const char *base_dir); RC init_record_handler(const char *base_dir);
RC make_record(int value_num, const Value *values, char *&record_out); 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(const char *index_name) const;
Index *find_index_by_field(const char *field_name) const;
private: private:
std::string base_dir_; std::string base_dir_;
......
...@@ -42,7 +42,8 @@ public: ...@@ -42,7 +42,8 @@ public:
const FieldMeta *field(int index) const; const FieldMeta *field(int index) const;
const FieldMeta *field(const char *name) const; const FieldMeta *field(const char *name) const;
const FieldMeta *find_field_by_offset(int offset) 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; int sys_field_num() const;
const IndexMeta *index(const char *name) const; const IndexMeta *index(const char *name) const;
...@@ -73,4 +74,4 @@ protected: ...@@ -73,4 +74,4 @@ protected:
static std::vector<FieldMeta> sys_fields_; static std::vector<FieldMeta> sys_fields_;
}; };
#endif // __OBSERVER_STORAGE_COMMON_TABLE_META_H__ #endif // __OBSERVER_STORAGE_COMMON_TABLE_META_H__
\ No newline at end of file
...@@ -97,9 +97,6 @@ public: ...@@ -97,9 +97,6 @@ public:
* 否则,创建该索引。 * 否则,创建该索引。
* 创建索引的工作包括:①创建并打开索引文件; * 创建索引的工作包括:①创建并打开索引文件;
* ②逐个扫描被索引的记录,并向索引文件中插入索引项;③关闭索引 * ②逐个扫描被索引的记录,并向索引文件中插入索引项;③关闭索引
* @param indexName
* @param relName
* @param attrName
* @return * @return
*/ */
RC create_index( RC create_index(
...@@ -118,9 +115,6 @@ public: ...@@ -118,9 +115,6 @@ public:
* nValues为属性值个数,values为对应的属性值数组。 * nValues为属性值个数,values为对应的属性值数组。
* 函数根据给定的属性值构建元组,调用记录管理模块的函数插入该元组, * 函数根据给定的属性值构建元组,调用记录管理模块的函数插入该元组,
* 然后在该表的每个索引中为该元组创建合适的索引项 * 然后在该表的每个索引中为该元组创建合适的索引项
* @param relName
* @param nValues
* @param values
* @return * @return
*/ */
RC insert_record(Trx *trx, const char *dbname, const char *relation_name, int value_num, const Value *values); RC insert_record(Trx *trx, const char *dbname, const char *relation_name, int value_num, const Value *values);
...@@ -142,11 +136,6 @@ public: ...@@ -142,11 +136,6 @@ public:
* 在每一个更新的元组中将属性attrName的值设置为一个新的值。 * 在每一个更新的元组中将属性attrName的值设置为一个新的值。
* 如果没有指定条件,则此方法更新relName中所有元组。 * 如果没有指定条件,则此方法更新relName中所有元组。
* 如果要更新一个被索引的属性,应当先删除每个被更新元组对应的索引条目,然后插入一个新的索引条目 * 如果要更新一个被索引的属性,应当先删除每个被更新元组对应的索引条目,然后插入一个新的索引条目
* @param relName
* @param attrName
* @param value
* @param nConditions
* @param conditions
* @return * @return
*/ */
RC update_record(Trx *trx, const char *dbname, const char *relation_name, const char *attribute_name, 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. */ ...@@ -29,7 +29,6 @@ See the Mulan PSL v2 for more details. */
#include "storage/common/table.h" #include "storage/common/table.h"
#include "storage/common/table_meta.h" #include "storage/common/table_meta.h"
#include "storage/trx/trx.h" #include "storage/trx/trx.h"
#include "event/execution_plan_event.h"
#include "event/session_event.h" #include "event/session_event.h"
#include "event/sql_event.h" #include "event/sql_event.h"
#include "event/storage_event.h" #include "event/storage_event.h"
...@@ -143,21 +142,15 @@ void DefaultStorageStage::handle_event(StageEvent *event) ...@@ -143,21 +142,15 @@ void DefaultStorageStage::handle_event(StageEvent *event)
LOG_TRACE("Enter\n"); LOG_TRACE("Enter\n");
TimerStat timerStat(*query_metric_); TimerStat timerStat(*query_metric_);
StorageEvent *storage_event = static_cast<StorageEvent *>(event); SQLStageEvent *sql_event = static_cast<SQLStageEvent *>(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);
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; 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(); Trx *current_trx = session->current_trx();
...@@ -165,78 +158,6 @@ void DefaultStorageStage::handle_event(StageEvent *event) ...@@ -165,78 +158,6 @@ void DefaultStorageStage::handle_event(StageEvent *event)
char response[256]; char response[256];
switch (sql->flag) { 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: { case SCF_LOAD_DATA: {
/* /*
从文件导入数据,如果做性能测试,需要保持这些代码可以正常工作 从文件导入数据,如果做性能测试,需要保持这些代码可以正常工作
...@@ -244,7 +165,7 @@ void DefaultStorageStage::handle_event(StageEvent *event) ...@@ -244,7 +165,7 @@ void DefaultStorageStage::handle_event(StageEvent *event)
*/ */
const char *table_name = sql->sstr.load_data.relation_name; const char *table_name = sql->sstr.load_data.relation_name;
const char *file_name = sql->sstr.load_data.file_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()); snprintf(response, sizeof(response), "%s", result.c_str());
} break; } break;
default: default:
...@@ -269,7 +190,7 @@ void DefaultStorageStage::callback_event(StageEvent *event, CallbackContext *con ...@@ -269,7 +190,7 @@ void DefaultStorageStage::callback_event(StageEvent *event, CallbackContext *con
{ {
LOG_TRACE("Enter\n"); LOG_TRACE("Enter\n");
StorageEvent *storage_event = static_cast<StorageEvent *>(event); StorageEvent *storage_event = static_cast<StorageEvent *>(event);
storage_event->exe_event()->done_immediate(); storage_event->sql_event()->done_immediate();
LOG_TRACE("Exit\n"); LOG_TRACE("Exit\n");
return; return;
} }
...@@ -411,4 +332,4 @@ std::string DefaultStorageStage::load_data(const char *db_name, const char *tabl ...@@ -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; << " record(s) loaded, total cost " << cost_nano / 1000000000.0 << " second(s)" << std::endl;
} }
return result_string.str(); return result_string.str();
} }
\ No newline at end of file
...@@ -25,11 +25,10 @@ See the Mulan PSL v2 for more details. */ ...@@ -25,11 +25,10 @@ See the Mulan PSL v2 for more details. */
#include <unordered_map> #include <unordered_map>
#include "rc.h" #include "rc.h"
#include "defs.h"
#include "common/mm/mem_pool.h" #include "common/mm/mem_pool.h"
#include "common/lang/bitmap.h" #include "common/lang/bitmap.h"
typedef int32_t PageNum;
class BufferPoolManager; class BufferPoolManager;
class DiskBufferPool; class DiskBufferPool;
......
...@@ -59,7 +59,7 @@ RC Trx::insert_record(Table *table, Record *record) ...@@ -59,7 +59,7 @@ RC Trx::insert_record(Table *table, Record *record)
{ {
RC rc = RC::SUCCESS; RC rc = RC::SUCCESS;
// 先校验是否以前是否存在过(应该不会存在) // 先校验是否以前是否存在过(应该不会存在)
Operation *old_oper = find_operation(table, record->rid); Operation *old_oper = find_operation(table, record->rid());
if (old_oper != nullptr) { if (old_oper != nullptr) {
return RC::GENERIC_ERROR; // error code return RC::GENERIC_ERROR; // error code
} }
...@@ -69,7 +69,7 @@ RC Trx::insert_record(Table *table, Record *record) ...@@ -69,7 +69,7 @@ RC Trx::insert_record(Table *table, Record *record)
// 设置record中trx_field为当前的事务号 // 设置record中trx_field为当前的事务号
// set_record_trx_id(table, record, trx_id_, false); // set_record_trx_id(table, record, trx_id_, false);
// 记录到operations中 // 记录到operations中
insert_operation(table, Operation::Type::INSERT, record->rid); insert_operation(table, Operation::Type::INSERT, record->rid());
return rc; return rc;
} }
...@@ -77,24 +77,24 @@ RC Trx::delete_record(Table *table, Record *record) ...@@ -77,24 +77,24 @@ RC Trx::delete_record(Table *table, Record *record)
{ {
RC rc = RC::SUCCESS; RC rc = RC::SUCCESS;
start_if_not_started(); 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 != nullptr) {
if (old_oper->type() == Operation::Type::INSERT) { if (old_oper->type() == Operation::Type::INSERT) {
delete_operation(table, record->rid); delete_operation(table, record->rid());
return RC::SUCCESS; return RC::SUCCESS;
} else { } else {
return RC::GENERIC_ERROR; return RC::GENERIC_ERROR;
} }
} }
set_record_trx_id(table, *record, trx_id_, true); 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; return rc;
} }
void Trx::set_record_trx_id(Table *table, Record &record, int32_t trx_id, bool deleted) const 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(); 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) { if (deleted) {
trx_id |= DELETED_FLAG_BIT_MASK; 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 ...@@ -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) 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(); 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; trx_id = trx & TRX_ID_BIT_MASK;
deleted = (trx & DELETED_FLAG_BIT_MASK) != 0; deleted = (trx & DELETED_FLAG_BIT_MASK) != 0;
} }
...@@ -261,4 +261,4 @@ void Trx::start_if_not_started() ...@@ -261,4 +261,4 @@ void Trx::start_if_not_started()
if (trx_id_ == 0) { if (trx_id_ == 0) {
trx_id_ = next_trx_id(); 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.
先完成此消息的编辑!
想要评论请 注册