From e279dc7ad0aeb643cd5789932df1ce25fb3dc3d3 Mon Sep 17 00:00:00 2001 From: wangyunlai Date: Mon, 5 Dec 2022 11:59:56 +0800 Subject: [PATCH] mysql communicator (#124) tested by mariadb ( Ver 15.1 Distrib 5.5.65-MariaDB, for Linux (x86_64) using readline 5.1) but failed with obclient --- CMakeLists.txt | 2 +- deps/common/os/process_param.h | 11 + src/observer/event/session_event.cpp | 22 +- src/observer/event/session_event.h | 25 +- src/observer/event/sql_event.h | 4 +- src/observer/main.cpp | 12 +- src/observer/net/communicator.cpp | 280 ++++++ src/observer/net/communicator.h | 107 +++ src/observer/net/mysql_communicator.cpp | 823 ++++++++++++++++++ src/observer/net/mysql_communicator.h | 76 ++ src/observer/net/server.cpp | 121 +-- src/observer/net/server.h | 22 +- src/observer/net/server_param.h | 8 +- src/observer/session/session_stage.cpp | 19 +- src/observer/session/session_stage.h | 1 - src/observer/sql/executor/execute_stage.cpp | 179 ++-- src/observer/sql/executor/sql_result.cpp | 48 + src/observer/sql/executor/sql_result.h | 49 ++ src/observer/sql/expr/expression.cpp | 2 +- src/observer/sql/expr/expression.h | 10 + src/observer/sql/expr/tuple.h | 116 +-- src/observer/sql/expr/tuple_cell.cpp | 21 + src/observer/sql/expr/tuple_cell.h | 16 + src/observer/sql/operator/delete_operator.h | 2 - .../operator/operator.cpp} | 26 +- src/observer/sql/operator/operator.h | 6 +- .../sql/operator/predicate_operator.cpp | 9 - .../sql/operator/predicate_operator.h | 2 - .../sql/operator/project_operator.cpp | 8 +- src/observer/sql/operator/project_operator.h | 2 - .../sql/operator/string_list_operator.h | 89 ++ .../sql/operator/table_scan_operator.h | 8 +- src/observer/sql/parser/parse.cpp | 82 +- src/observer/sql/parser/parse_defs.h | 31 +- src/observer/sql/parser/parse_stage.cpp | 5 +- src/observer/sql/parser/resolve_stage.cpp | 4 +- src/observer/sql/parser/yacc_sql.cpp | 793 +++++++++-------- src/observer/sql/parser/yacc_sql.hpp | 2 +- src/observer/sql/parser/yacc_sql.y | 422 +++++---- src/observer/storage/common/field_meta.cpp | 20 +- src/observer/storage/common/field_meta.h | 4 +- src/observer/storage/common/table.h | 5 +- src/observer/storage/common/table_meta.h | 5 +- .../storage/default/default_storage_stage.cpp | 2 +- 44 files changed, 2474 insertions(+), 1027 deletions(-) create mode 100644 src/observer/net/communicator.cpp create mode 100644 src/observer/net/communicator.h create mode 100644 src/observer/net/mysql_communicator.cpp create mode 100644 src/observer/net/mysql_communicator.h create mode 100644 src/observer/sql/executor/sql_result.cpp create mode 100644 src/observer/sql/executor/sql_result.h rename src/observer/{net/connection_context.h => sql/operator/operator.cpp} (56%) create mode 100644 src/observer/sql/operator/string_list_operator.h diff --git a/CMakeLists.txt b/CMakeLists.txt index d772f54..ca105fa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,7 +55,7 @@ SET(CMAKE_CXX_FLAGS ${CMAKE_COMMON_FLAGS}) SET(CMAKE_C_FLAGS ${CMAKE_COMMON_FLAGS}) MESSAGE("CMAKE_CXX_FLAGS is " ${CMAKE_CXX_FLAGS}) -OPTION(ENABLE_ASAN OFF "Enable build with address sanitizer") +OPTION(ENABLE_ASAN "Enable build with address sanitizer" ON) IF (ENABLE_ASAN) SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-omit-frame-pointer -fsanitize=address") diff --git a/deps/common/os/process_param.h b/deps/common/os/process_param.h index 614beb8..228916d 100644 --- a/deps/common/os/process_param.h +++ b/deps/common/os/process_param.h @@ -110,6 +110,16 @@ public: return unix_socket_path_; } + void set_protocol(const char *protocol) + { + protocol_ = protocol; + } + + const std::string &get_protocol() const + { + return protocol_; + } + private: std::string std_out_; // The output file std::string std_err_; // The err output file @@ -119,6 +129,7 @@ private: std::vector args; // arguments int server_port_ = -1; // server port(if valid, will overwrite the port in the config file) std::string unix_socket_path_; + std::string protocol_; }; ProcessParam *&the_process_param(); diff --git a/src/observer/event/session_event.cpp b/src/observer/event/session_event.cpp index 1ba7b4d..e6b6577 100644 --- a/src/observer/event/session_event.cpp +++ b/src/observer/event/session_event.cpp @@ -13,23 +13,28 @@ See the Mulan PSL v2 for more details. */ // #include "session_event.h" +#include "net/communicator.h" -SessionEvent::SessionEvent(ConnectionContext *client) : client_(client) +SessionEvent::SessionEvent(Communicator *comm) : communicator_(comm) { } SessionEvent::~SessionEvent() { + if (sql_result_) { + delete sql_result_; + sql_result_ = nullptr; + } } -ConnectionContext *SessionEvent::get_client() const +Communicator *SessionEvent::get_communicator() const { - return client_; + return communicator_; } Session *SessionEvent::session() const { - return client_->session; + return communicator_->session(); } const char *SessionEvent::get_response() const @@ -57,12 +62,7 @@ int SessionEvent::get_response_len() const return response_.size(); } -char *SessionEvent::get_request_buf() +const char *SessionEvent::get_request_buf() { - return client_->buf; -} - -int SessionEvent::get_request_buf_len() -{ - return SOCKET_BUFFER_SIZE; + return query_.c_str(); } diff --git a/src/observer/event/session_event.h b/src/observer/event/session_event.h index 933aafd..047099b 100644 --- a/src/observer/event/session_event.h +++ b/src/observer/event/session_event.h @@ -12,37 +12,42 @@ See the Mulan PSL v2 for more details. */ // Created by Longda on 2021/4/13. // -#ifndef __OBSERVER_SESSION_SESSIONEVENT_H__ -#define __OBSERVER_SESSION_SESSIONEVENT_H__ +#pragma once #include #include #include "common/seda/stage_event.h" -#include "net/connection_context.h" +#include "sql/executor/sql_result.h" class Session; +class Communicator; +class SqlResult; class SessionEvent : public common::StageEvent { public: - SessionEvent(ConnectionContext *client); + SessionEvent(Communicator *client); virtual ~SessionEvent(); - ConnectionContext *get_client() const; + Communicator *get_communicator() const; Session *session() const; + void set_query(const std::string &query) { query_ = query; } + void set_sql_result(SqlResult *result) { sql_result_ = result; } + const std::string &query() const { return query_; } + SqlResult *sql_result() const { return sql_result_; } + const char *get_response() const; void set_response(const char *response); void set_response(const char *response, int len); void set_response(std::string &&response); int get_response_len() const; - char *get_request_buf(); - int get_request_buf_len(); + const char *get_request_buf(); // TODO remove me private: - ConnectionContext *client_; + Communicator *communicator_ = nullptr; + SqlResult *sql_result_ = nullptr; + std::string query_; std::string response_; }; - -#endif //__OBSERVER_SESSION_SESSIONEVENT_H__ diff --git a/src/observer/event/sql_event.h b/src/observer/event/sql_event.h index c1b5ad6..b74b58a 100644 --- a/src/observer/event/sql_event.h +++ b/src/observer/event/sql_event.h @@ -12,8 +12,7 @@ See the Mulan PSL v2 for more details. */ // Created by Longda on 2021/4/14. // -#ifndef __OBSERVER_SQL_EVENT_SQLEVENT_H__ -#define __OBSERVER_SQL_EVENT_SQLEVENT_H__ +#pragma once #include #include "common/seda/stage_event.h" @@ -48,4 +47,3 @@ private: Stmt *stmt_ = nullptr; }; -#endif //__SRC_OBSERVER_SQL_EVENT_SQLEVENT_H__ diff --git a/src/observer/main.cpp b/src/observer/main.cpp index 112255e..2453907 100644 --- a/src/observer/main.cpp +++ b/src/observer/main.cpp @@ -20,6 +20,7 @@ See the Mulan PSL v2 for more details. */ #include #include "init.h" +#include "ini_setting.h" #include "common/os/process.h" #include "common/os/signal.h" #include "net/server.h" @@ -37,6 +38,7 @@ void usage() std::cout << "-p: server port. if not specified, the item in the config file will be used" << std::endl; std::cout << "-f: path of config file." << std::endl; std::cout << "-s: use unix socket and the argument is socket address" << std::endl; + std::cout << "-P: protocol. {plain, mysql}. plain is default." << std::endl; exit(0); } @@ -51,7 +53,7 @@ void parse_parameter(int argc, char **argv) // Process args int opt; extern char *optarg; - while ((opt = getopt(argc, argv, "dp:s:f:o:e:h")) > 0) { + while ((opt = getopt(argc, argv, "dp:P:s:f:o:e:h")) > 0) { switch (opt) { case 's': process_param->set_unix_socket_path(optarg); @@ -59,6 +61,9 @@ void parse_parameter(int argc, char **argv) case 'p': process_param->set_server_port(atoi(optarg)); break; + case 'P': + process_param->set_protocol(optarg); + break; case 'f': process_param->set_conf(optarg); break; @@ -116,6 +121,11 @@ Server *init_server() server_param.listen_addr = listen_addr; server_param.max_connection_num = max_connection_num; server_param.port = port; + if (0 == strcasecmp(process_param->get_protocol().c_str(), "mysql")) { + server_param.protocol = CommunicateProtocol::MYSQL; + } else { + server_param.protocol = CommunicateProtocol::PLAIN; + } if (process_param->get_unix_socket_path().size() > 0) { server_param.use_unix_socket = true; diff --git a/src/observer/net/communicator.cpp b/src/observer/net/communicator.cpp new file mode 100644 index 0000000..58bb38c --- /dev/null +++ b/src/observer/net/communicator.cpp @@ -0,0 +1,280 @@ +/* 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/11/17. +// + +#include "net/communicator.h" +#include "net/mysql_communicator.h" +#include "sql/expr/tuple.h" +#include "event/session_event.h" +#include "common/lang/mutex.h" +#include "common/io/io.h" +#include "session/session.h" + + +RC Communicator::init(int fd, Session *session, const std::string &addr) +{ + fd_ = fd; + session_ = session; + addr_ = addr; + return RC::SUCCESS; +} + +Communicator::~Communicator() +{ + if (fd_ >= 0) { + close(fd_); + fd_ = -1; + } + if (session_ != nullptr) { + delete session_; + session_ = nullptr; + } +} + +///////////////////////////////////////////////////////////////////////////////// +RC PlainCommunicator::read_event(SessionEvent *&event) +{ + RC rc = RC::SUCCESS; + + event = nullptr; + + int data_len = 0; + int read_len = 0; + + const int max_packet_size = 8192; + std::vector buf(max_packet_size); + + // 持续接收消息,直到遇到'\0'。将'\0'遇到的后续数据直接丢弃没有处理,因为目前仅支持一收一发的模式 + while (true) { + read_len = ::read(fd_, buf.data() + data_len, max_packet_size - data_len); + if (read_len < 0) { + if (errno == EAGAIN) { + continue; + } + break; + } + if (read_len == 0) { + break; + } + + if (read_len + data_len > max_packet_size) { + data_len += read_len; + break; + } + + bool msg_end = false; + for (int i = 0; i < read_len; i++) { + if (buf[data_len + i] == 0) { + data_len += i + 1; + msg_end = true; + break; + } + } + + if (msg_end) { + break; + } + + data_len += read_len; + } + + + if (data_len > max_packet_size) { + LOG_WARN("The length of sql exceeds the limitation %d", max_packet_size); + return RC::IOERR; + } + if (read_len == 0) { + LOG_INFO("The peer has been closed %s\n", addr()); + return RC::IOERR; + } else if (read_len < 0) { + LOG_ERROR("Failed to read socket of %s, %s\n", addr(), strerror(errno)); + return RC::IOERR; + } + + LOG_INFO("receive command(size=%d): %s", data_len, buf.data()); + event = new SessionEvent(this); + event->set_query(std::string(buf.data())); + return rc; +} + + +RC PlainCommunicator::write_state(SessionEvent *event, bool &need_disconnect) +{ + SqlResult *sql_result = event->sql_result(); + const int buf_size = 2048; + char *buf = new char[buf_size]; + const std::string &state_string = sql_result->state_string(); + if (state_string.empty()) { + const char *result = RC::SUCCESS == sql_result->return_code() ? "SUCCESS" : "FAILURE"; + snprintf(buf, buf_size, "%s\n", result); + } else { + snprintf(buf, buf_size, "%s > %s\n", strrc(sql_result->return_code()), state_string.c_str()); + } + + int ret = common::writen(fd_, buf, strlen(buf) + 1); + if (ret != 0) { + LOG_WARN("failed to send data to client. err=%s", strerror(errno)); + need_disconnect = true; + delete[] buf; + return RC::IOERR; + } + + need_disconnect = false; + delete[] buf; + return RC::SUCCESS; +} + +RC PlainCommunicator::write_result(SessionEvent *event, bool &need_disconnect) +{ + need_disconnect = true; + + const char message_terminate = '\0'; + + SqlResult *sql_result = event->sql_result(); + if (nullptr == sql_result) { + + const char *response = event->get_response(); + int len = event->get_response_len(); + + int ret = common::writen(fd_, response, len); + if (ret < 0) { + LOG_ERROR("Failed to send data back to client. ret=%d, error=%s", ret, strerror(errno)); + + return RC::IOERR; + } + ret = common::writen(fd_, &message_terminate, sizeof(message_terminate)); + if (ret < 0) { + LOG_ERROR("Failed to send data back to client. ret=%d, error=%s", ret, strerror(errno)); + return RC::IOERR; + } + + need_disconnect = false; + return RC::SUCCESS; + } + + if (RC::SUCCESS != sql_result->return_code() || !sql_result->has_operator()) { + return write_state(event, need_disconnect); + } + + RC rc = sql_result->open(); + if (rc != RC::SUCCESS) { + sql_result->set_return_code(rc); + return write_state(event, need_disconnect); + } + + const TupleSchema &schema = sql_result->tuple_schema(); + const int cell_num = schema.cell_num(); + + for (int i = 0; i < cell_num; i++) { + const TupleCellSpec &spec = schema.cell_at(i); + const char *alias = spec.alias(); + if (nullptr != alias || alias[0] != 0) { + if (0 != i) { + const char *delim = " | "; + int ret = common::writen(fd_, delim, strlen(delim)); + if (ret != 0) { + LOG_WARN("failed to send data to client. err=%s", strerror(errno)); + return RC::IOERR; + } + } + + int len = strlen(alias); + int ret = common::writen(fd_, alias, len); + if (ret != 0) { + LOG_WARN("failed to send data to client. err=%s", strerror(errno)); + return RC::IOERR; + } + } + } + + if (cell_num > 0) { + char newline = '\n'; + int ret = common::writen(fd_, &newline, 1); + if (ret != 0) { + LOG_WARN("failed to send data to client. err=%s", strerror(errno)); + return RC::IOERR; + } + } + + rc = RC::SUCCESS; + Tuple *tuple = nullptr; + while (RC::SUCCESS == (rc = sql_result->next_tuple(tuple))) { + assert(tuple != nullptr); + + int cell_num = tuple->cell_num(); + for (int i = 0; i < cell_num; i++) { + if (i != 0) { + const char *delim = " | "; + int ret = common::writen(fd_, delim, strlen(delim)); + if (ret != 0) { + LOG_WARN("failed to send data to client. err=%s", strerror(errno)); + return RC::IOERR; + } + } + + TupleCell cell; + rc = tuple->cell_at(i, cell); + if (rc != RC::SUCCESS) { + return rc; + } + + std::stringstream ss; + cell.to_string(ss); + std::string cell_str = ss.str(); + int ret = common::writen(fd_, cell_str.data(), cell_str.size()); + if (ret != RC::SUCCESS) { + LOG_WARN("failed to send data to client. err=%s", strerror(errno)); + return RC::IOERR; + } + } + + char newline = '\n'; + int ret = common::writen(fd_, &newline, 1); + if (ret != 0) { + LOG_WARN("failed to send data to client. err=%s", strerror(errno)); + return RC::IOERR; + } + } + + if (rc != RC::RECORD_EOF) { + LOG_WARN("operator is done with error. error=%s", strrc(rc)); + } else { + rc = RC::SUCCESS; + int ret = common::writen(fd_, &message_terminate, sizeof(message_terminate)); + if (ret < 0) { + LOG_ERROR("Failed to send data back to client. ret=%d, error=%s", ret, strerror(errno)); + return RC::IOERR; + } + + need_disconnect = false; + } + return rc; +} + +///////////////////////////////////////////////////////////////////////////////// + + +Communicator *CommunicatorFactory::create(CommunicateProtocol protocol) +{ + switch (protocol) { + case CommunicateProtocol::PLAIN: { + return new PlainCommunicator; + } break; + case CommunicateProtocol::MYSQL: { + return new MysqlCommunicator; + } break; + default: { + return nullptr; + } + } +} diff --git a/src/observer/net/communicator.h b/src/observer/net/communicator.h new file mode 100644 index 0000000..9e58792 --- /dev/null +++ b/src/observer/net/communicator.h @@ -0,0 +1,107 @@ +/* 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/11/17. +// + +#pragma once + +#include +#include +#include "rc.h" + +struct ConnectionContext; +class SessionEvent; +class Session; + +/** + * 负责与客户端通讯 + * + * 在listener接收到一个新的连接(参考 server.cpp::accept), 就创建一个Communicator对象。 + * 并调用init进行初始化。 + * 在server中监听到某个连接有新的消息,就通过Communicator::read_event接收消息。 + + */ +class Communicator { +public: + virtual ~Communicator(); + + /** + * 接收到一个新的连接时,进行初始化 + */ + virtual RC init(int fd, Session *session, const std::string &addr); + + /** + * 监听到有新的数据到达,调用此函数进行接收消息 + * 如果需要创建新的任务来处理,那么就创建一个SessionEvent 对象并通过event参数返回。 + */ + virtual RC read_event(SessionEvent *&event) = 0; + + /** + * 在任务处理完成后,通过此接口将结果返回给客户端 + * @param event 任务数据,包括处理的结果 + * @param need_disconnect 是否需要断开连接 + * @return 处理结果。即使返回不是SUCCESS,也不能直接断开连接,需要通过need_disconnect来判断 + * 是否需要断开连接 + */ + virtual RC write_result(SessionEvent *event, bool &need_disconnect) = 0; + + /** + * 关联的会话信息 + */ + Session *session() const { return session_; } + + /** + * libevent使用的数据,参考server.cpp + */ + struct event &read_event() { return read_event_; } + + /** + * 对端地址 + * 如果是unix socket,可能没有意义 + */ + const char *addr() const { return addr_.c_str(); } + +protected: + Session *session_ = nullptr; + int fd_ = -1; + struct event read_event_; + std::string addr_; +}; + +/** + * 与客户端进行通讯 + * 使用简单的文本通讯协议,每个消息使用'\0'结尾 + */ +class PlainCommunicator : public Communicator { +public: + RC read_event(SessionEvent *&event) override; + RC write_result(SessionEvent *event, bool &need_disconnect) override; + +private: + RC write_state(SessionEvent *event, bool &need_disconnect); + +}; + +/** + * 当前支持的通讯协议 + */ +enum class CommunicateProtocol +{ + PLAIN, //! 以'\0'结尾的协议 + MYSQL, //! mysql通讯协议。具体实现参考 MysqlCommunicator +}; + +class CommunicatorFactory +{ +public: + Communicator *create(CommunicateProtocol protocol); +}; diff --git a/src/observer/net/mysql_communicator.cpp b/src/observer/net/mysql_communicator.cpp new file mode 100644 index 0000000..822e6a3 --- /dev/null +++ b/src/observer/net/mysql_communicator.cpp @@ -0,0 +1,823 @@ +/* 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/11/22. +// + +#include +#include + +#include "common/log/log.h" +#include "common/io/io.h" +#include "net/mysql_communicator.h" +#include "event/session_event.h" +#include "sql/operator/string_list_operator.h" + +// https://dev.mysql.com/doc/dev/mysql-server/latest/group__group__cs__capabilities__flags.html +// the flags below are negotiate by handshake packet +const uint32_t CLIENT_PROTOCOL_41 = 512; +const uint32_t CLIENT_INTERACTIVE = 1024; // This is an interactive client +const uint32_t CLIENT_TRANSACTIONS = 8192; // Client knows about transactions. +const uint32_t CLIENT_SESSION_TRACK = (1UL << 23); // Capable of handling server state change information +const uint32_t CLIENT_DEPRECATE_EOF = (1UL << 24); // Client no longer needs EOF_Packet and will use OK_Packet instead +const uint32_t CLIENT_OPTIONAL_RESULTSET_METADATA = (1UL << 25); // The client can handle optional metadata information in the resultset. +// Support optional extension for query parameters into the COM_QUERY and COM_STMT_EXECUTE packets. +const uint32_t CLIENT_QUERY_ATTRIBUTES = (1UL << 27); + +// https://dev.mysql.com/doc/dev/mysql-server/latest/group__group__cs__column__definition__flags.html +// Column Definition Flags +const uint32_t NOT_NULL_FLAG = 1; +const uint32_t PRI_KEY_FLAG = 2; +const uint32_t UNIQUE_KEY_FLAG = 4; +const uint32_t MULTIPLE_KEY_FLAG = 8; +const uint32_t NUM_FLAG = 32768; // Field is num (for clients) +const uint32_t PART_KEY_FLAG = 16384; // Intern; Part of some key. + +enum ResultSetMetaData +{ + RESULTSET_METADATA_NONE = 0, + RESULTSET_METADATA_FULL = 1, +}; + + +/** + Column types for MySQL +*/ +enum enum_field_types { + MYSQL_TYPE_DECIMAL, + MYSQL_TYPE_TINY, + MYSQL_TYPE_SHORT, + MYSQL_TYPE_LONG, + MYSQL_TYPE_FLOAT, + MYSQL_TYPE_DOUBLE, + MYSQL_TYPE_NULL, + MYSQL_TYPE_TIMESTAMP, + MYSQL_TYPE_LONGLONG, + MYSQL_TYPE_INT24, + MYSQL_TYPE_DATE, + MYSQL_TYPE_TIME, + MYSQL_TYPE_DATETIME, + MYSQL_TYPE_YEAR, + MYSQL_TYPE_NEWDATE, /**< Internal to MySQL. Not used in protocol */ + MYSQL_TYPE_VARCHAR, + MYSQL_TYPE_BIT, + MYSQL_TYPE_TIMESTAMP2, + MYSQL_TYPE_DATETIME2, /**< Internal to MySQL. Not used in protocol */ + MYSQL_TYPE_TIME2, /**< Internal to MySQL. Not used in protocol */ + MYSQL_TYPE_TYPED_ARRAY, /**< Used for replication only */ + MYSQL_TYPE_INVALID = 243, + MYSQL_TYPE_BOOL = 244, /**< Currently just a placeholder */ + MYSQL_TYPE_JSON = 245, + MYSQL_TYPE_NEWDECIMAL = 246, + MYSQL_TYPE_ENUM = 247, + MYSQL_TYPE_SET = 248, + MYSQL_TYPE_TINY_BLOB = 249, + MYSQL_TYPE_MEDIUM_BLOB = 250, + MYSQL_TYPE_LONG_BLOB = 251, + MYSQL_TYPE_BLOB = 252, + MYSQL_TYPE_VAR_STRING = 253, + MYSQL_TYPE_STRING = 254, + MYSQL_TYPE_GEOMETRY = 255 +}; + +// little endian +// We suppose our platform is little endian too +int store_int1(char *buf, int8_t value) +{ + *buf = value; + return 1; +} + +int store_int2(char *buf, int16_t value) +{ + memcpy(buf, &value, sizeof(value)); + return 2; +} + +int store_int3(char *buf, int32_t value) +{ + memcpy(buf, &value, 3); + return 3; +} + +int store_int4(char *buf, int32_t value) +{ + memcpy(buf, &value, 4); + return 4; +} + +int store_int6(char *buf, int64_t value) +{ + memcpy(buf, &value, 6); + return 6; +} + +int store_int8(char *buf, int64_t value) +{ + memcpy(buf, &value, 8); + return 8; +} + +int store_lenenc_int(char *buf, uint64_t value) +{ + if (value < 251) { + *buf = (int8_t)value; + return 1; + } + + if (value < (2UL << 16)) { + *buf = 0xFC; + memcpy(buf + 1, &value, 2); + return 3; + } + + if (value < (2UL << 24)) { + *buf = 0xFD; + memcpy(buf + 1, &value, 3); + return 4; + } + + *buf = 0xFE; + memcpy(buf + 1, &value, 8); + return 9; +} + +int store_null_terminated_string(char *buf, const char *s) +{ + if (nullptr == s || s[0] == 0) { + return 0; + } + + const int len = strlen(s) + 1; + memcpy(buf, s, len); + return len; +} + +int store_fix_length_string(char *buf, const char *s, int len) +{ + if (len == 0) { + return 0; + } + + memcpy(buf, s, len); + return len; +} + +int store_lenenc_string(char *buf, const char *s) +{ + int len = strlen(s); + int pos = store_lenenc_int(buf, len); + store_fix_length_string(buf + pos, s, len); + return pos + len; +} + +/** + * 每个包都有一个包头 + * https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_basic_packets.html + * https://mariadb.com/kb/en/0-packet/ + */ +struct alignas(1) PacketHeader { + int32_t payload_length:24; //! 当前packet的除掉头的长度 + int8_t sequence_id = 0; //! 当前packet在当前处理过程中是第几个包 +}; + +class BasePacket +{ +public: + PacketHeader packet_header; + + BasePacket(int8_t sequence = 0) + { + packet_header.sequence_id = sequence; + } + + virtual ~BasePacket() = default; + virtual RC encode(uint32_t capabilities, std::vector &net_packet) const = 0; +}; + +/** + * 握手包 + * 先由服务端发送到客户端 + * 这个包会交互capability与用户名密码 + * https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_connection_phase_packets_protocol_handshake_v10.html + */ +struct HandshakeV10 : public BasePacket +{ + int8_t protocol = 10; + char server_version[7] = "5.7.25"; + int32_t thread_id = 3221501807; // conn id + char auth_plugin_data_part_1[9] = "12345678"; // first 8 bytes of the plugin provided data (scramble) // and the filler + int16_t capability_flags_1 = 0xF7DF; // The lower 2 bytes of the Capabilities Flags + int8_t character_set = 83; + int16_t status_flags = 0; + int16_t capability_flags_2 = 0x0000; + int8_t auth_plugin_data_len = 0; + char reserved[10] = {0}; + char auth_plugin_data_part_2[13] = "bbbbbbbbbbbb"; + + HandshakeV10(int8_t sequence = 0) : BasePacket(sequence) + {} + virtual ~HandshakeV10() = default; + + /** + * https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_connection_phase_packets_protocol_handshake_v10.html + */ + virtual RC encode(uint32_t capabilities, std::vector &net_packet) const override + { + net_packet.resize(100); + + char *buf = net_packet.data(); + int pos = 0; + pos += 3; + + pos += store_int1(buf + pos, packet_header.sequence_id); + pos += store_int1(buf + pos, protocol); + + pos += store_null_terminated_string(buf + pos, server_version); + pos += store_int4(buf + pos, thread_id); + pos += store_null_terminated_string(buf + pos, auth_plugin_data_part_1); + pos += store_int2(buf + pos, capability_flags_1); + pos += store_int1(buf + pos, character_set); + pos += store_int2(buf + pos, status_flags); + pos += store_int2(buf + pos, capability_flags_2); + pos += store_int1(buf + pos, auth_plugin_data_len); + pos += store_fix_length_string(buf + pos, reserved, 10); + pos += store_null_terminated_string(buf + pos, auth_plugin_data_part_2); + + int payload_length = pos - 4; + store_int3(buf, payload_length); + net_packet.resize(pos); + LOG_TRACE("encode handshake packet with payload length=%d", payload_length); + + return RC::SUCCESS; + } +}; + +struct OkPacket : public BasePacket +{ + int8_t header = 0; // 0x00 for ok and 0xFE for EOF + int32_t affected_rows = 0; + int32_t last_insert_id = 0; + int16_t status_flags = 0x22; + int16_t warnings = 0; + std::string info; // human readable status information + + OkPacket(int8_t sequence = 0) : BasePacket(sequence) + {} + virtual ~OkPacket() = default; + + /** + * https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_basic_ok_packet.html + */ + virtual RC encode(uint32_t capabilities, std::vector &net_packet) const override + { + net_packet.resize(100); + char *buf = net_packet.data(); + int pos = 0; + + pos += 3; + pos += store_int1(buf + pos, packet_header.sequence_id); + pos += store_int1(buf + pos, header); + pos += store_lenenc_int(buf + pos, affected_rows); + pos += store_lenenc_int(buf + pos, last_insert_id); + + if (capabilities & CLIENT_PROTOCOL_41) { + pos += store_int2(buf + pos, status_flags); + pos += store_int2(buf + pos, warnings); + } else if (capabilities & CLIENT_TRANSACTIONS) { + pos += store_int2(buf + pos, status_flags); + } + + if (capabilities & CLIENT_SESSION_TRACK) { + pos += store_lenenc_string(buf + pos, info.c_str()); + } else { + pos += store_fix_length_string(buf + pos, info.c_str(), info.length()); + } + + int32_t payload_length = pos - 4; + LOG_TRACE("encode ok packet with length=%d", payload_length); + store_int3(buf, payload_length); + net_packet.resize(pos); + return RC::SUCCESS; + } +}; + +struct EofPacket : public BasePacket +{ + int8_t header = 0xFE; + int16_t warnings = 0; + int16_t status_flags = 0x22; + + EofPacket(int8_t sequence = 0) : BasePacket(sequence) + {} + virtual ~EofPacket() = default; + + /** + * https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_basic_err_packet.html + */ + virtual RC encode(uint32_t capabilities, std::vector &net_packet) const override + { + net_packet.resize(10); + char *buf = net_packet.data(); + int pos = 0; + + pos += 3; + store_int1(buf + pos, packet_header.sequence_id); + pos += 1; + store_int1(buf + pos, header); + pos += 1; + + if (capabilities & CLIENT_PROTOCOL_41) { + store_int2(buf + pos, warnings); + pos += 2; + store_int2(buf + pos, status_flags); + pos += 2; + } + + int payload_length = pos - 4; + store_int3(buf, payload_length); + net_packet.resize(pos); + + return RC::SUCCESS; + } +}; + +struct ErrPacket : public BasePacket +{ + int8_t header = 0xFF; + int16_t error_code = 0; + char sql_state_marker[1] = {'#'}; + std::string sql_state{"HY000"}; + std::string error_message; + + ErrPacket(int8_t sequence = 0) : BasePacket(sequence) + {} + virtual ~ErrPacket() = default; + + /** + * https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_basic_eof_packet.html + */ + virtual RC encode(uint32_t capabilities, std::vector &net_packet) const override + { + net_packet.resize(1000); + char *buf = net_packet.data(); + int pos = 0; + + pos += 3; + + store_int1(buf + pos, packet_header.sequence_id); + pos += 1; + store_int1(buf + pos, header); + pos += 1; + store_int2(buf + pos, error_code); + pos += 2; + if (capabilities & CLIENT_PROTOCOL_41) { + pos += store_fix_length_string(buf + pos, sql_state_marker, 1); + pos += store_fix_length_string(buf + pos, sql_state.c_str(), 5); + } + + pos += store_fix_length_string(buf + pos, error_message.c_str(), error_message.length()); + + int payload_length = pos - 4; + store_int3(buf, payload_length); + net_packet.resize(pos); + return RC::SUCCESS; + } +}; + +// https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_command_phase.html +// https://mariadb.com/kb/en/2-text-protocol/ +struct QueryPacket +{ + PacketHeader packet_header; + int8_t command; // 0x03: COM_QUERY + std::string query; // the text of the SQL query to execute +}; + +/** + * decode query packet + * packet_header is not included in net_packet + * https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_com_query.html + */ +RC decode_query_packet(std::vector &net_packet, QueryPacket &query_packet) +{ + // query field is a null terminated string + query_packet.query.assign(net_packet.data() + 1, net_packet.size() - 1); + query_packet.query.append(1, ';'); + return RC::SUCCESS; +} + +RC create_version_comment_sql_result(SqlResult *&sql_result) +{ + TupleSchema tuple_schema; + TupleCellSpec cell_spec("", "", "@@version_comment"); + tuple_schema.append_cell(cell_spec); + + sql_result = new SqlResult; + sql_result->set_return_code(RC::SUCCESS); + sql_result->set_tuple_schema(tuple_schema); + + const char *version_comments = "MiniOB"; + + StringListOperator *oper = new StringListOperator(); + oper->append(version_comments); + sql_result->set_operator(oper); + return RC::SUCCESS; +} + +RC MysqlCommunicator::init(int fd, Session *session, const std::string &addr) +{ + // https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_connection_phase.html + // 按照协议描述,服务端在连接建立后需要先向客户端发送握手信息 + RC rc = Communicator::init(fd, session, addr); + if (rc != RC::SUCCESS) { + LOG_WARN("failed to init communicator: %s", strrc(rc)); + return rc; + } + + HandshakeV10 handshake_packet; + rc = send_packet(handshake_packet); + if (rc != RC::SUCCESS) { + LOG_WARN("failed to send handshake packet to client. addr=%s, error=%s", addr.c_str(), strerror(errno)); + return rc; + } + + return rc; +} + +RC MysqlCommunicator::handle_version_comment(bool &need_disconnect) +{ + SqlResult *sql_result = nullptr; + RC rc = create_version_comment_sql_result(sql_result); + if (rc != RC::SUCCESS) { + LOG_WARN("failed to handle version comment. rc=%s", strrc(rc)); + return rc; + } + + SessionEvent session_event(this); + session_event.set_sql_result(sql_result); + rc = write_result(&session_event, need_disconnect); + return rc; +} + +RC MysqlCommunicator::read_event(SessionEvent *&event) +{ + RC rc = RC::SUCCESS; + PacketHeader packet_header; + int ret = common::readn(fd_, &packet_header, sizeof(packet_header)); + if (ret != 0) { + LOG_WARN("failed to read packet header. length=%d, addr=%s. error=%s", sizeof(packet_header), addr_.c_str(), strerror(errno)); + return RC::IOERR; + } + + LOG_TRACE("read packet header. length=%d, sequence_id=%d", sizeof(packet_header), packet_header.sequence_id); + sequence_id_ = packet_header.sequence_id + 1; + + std::vector buf(packet_header.payload_length); + ret = common::readn(fd_, buf.data(), packet_header.payload_length); + if (ret != 0) { + LOG_WARN("failed to read packet payload. length=%d, addr=%s, error=%s", + packet_header.payload_length, addr_.c_str(), strerror(errno)); + return RC::IOERR; + } + + LOG_TRACE("read packet payload length=%d", packet_header.payload_length); + + event = nullptr; + if (!authed_) { + uint32_t client_flag = *(uint32_t*)buf.data(); // TODO should use decode (little endian as default) + LOG_INFO("client handshake response with capabilities flag=%d", client_flag); + client_capabilities_flag_ = client_flag; + // send ok packet and return + OkPacket ok_packet; + ok_packet.packet_header.sequence_id = sequence_id_; + rc = send_packet(ok_packet); + if (rc != RC::SUCCESS) { + LOG_WARN("failed to send ok packet while auth"); + } + authed_ = true; + LOG_INFO("client authed. addr=%s. rc=%s", addr_.c_str(), strrc(rc)); + return rc; + } + + int8_t command_type = buf[0]; + LOG_TRACE("recv command from client =%d", command_type); + + if (command_type == 0x03) { // COM_QUERY + QueryPacket query_packet; + rc = decode_query_packet(buf, query_packet); + if (rc != RC::SUCCESS) { + LOG_WARN("failed to decode query packet. packet length=%ld, addr=%s, error=%s", buf.size(), addr(), strrc(rc)); + return rc; + } + + LOG_TRACE("query command: %s", query_packet.query.c_str()); + if (query_packet.query.find("select @@version_comment") != std::string::npos) { + bool need_disconnect; + return handle_version_comment(need_disconnect); + } + + event = new SessionEvent(this); + event->set_query(query_packet.query); + } else { + OkPacket ok_packet(sequence_id_); + rc = send_packet(ok_packet); + if (rc != RC::SUCCESS) { + LOG_WARN("failed to send ok packet. command=%d, addr=%s, error=%s", command_type, addr(), strrc(rc)); + return rc; + } + } + return rc; +} + +RC MysqlCommunicator::write_state(SessionEvent *event, bool &need_disconnect) +{ + SqlResult *sql_result = event->sql_result(); + + const int buf_size = 2048; + char *buf = new char[buf_size]; + const std::string &state_string = sql_result->state_string(); + if (state_string.empty()) { + const char *result = RC::SUCCESS == sql_result->return_code() ? "SUCCESS" : "FAILURE"; + snprintf(buf, buf_size, "%s", result); + } else { + snprintf(buf, buf_size, "%s > %s", strrc(sql_result->return_code()), state_string.c_str()); + } + + RC rc = RC::SUCCESS; + if (sql_result->return_code() == RC::SUCCESS) { + + OkPacket ok_packet; + ok_packet.packet_header.sequence_id = sequence_id_++; + ok_packet.info.assign(buf); + rc = send_packet(ok_packet); + } else { + ErrPacket err_packet; + err_packet.packet_header.sequence_id = sequence_id_++; + err_packet.error_code = static_cast(sql_result->return_code()); + err_packet.error_message = buf; + rc = send_packet(err_packet); + } + if (rc != RC::SUCCESS) { + LOG_WARN("failed to send ok packet to client. addr=%s, error=%s", addr(), strrc(rc)); + need_disconnect = true; + } else { + need_disconnect = false; + } + + delete[] buf; + return rc; +} + +RC MysqlCommunicator::write_result(SessionEvent *event, bool &need_disconnect) +{ + RC rc = RC::SUCCESS; + + need_disconnect = true; + SqlResult *sql_result = event->sql_result(); + if (nullptr == sql_result) { + const char *response = event->get_response(); + int len = event->get_response_len(); + + OkPacket ok_packet;// TODO if error occurs, we should send an error packet to client + ok_packet.info.assign(response, len); + rc = send_packet(ok_packet); + if (rc != RC::SUCCESS) { + LOG_WARN("failed to send ok packet to client. addr=%s, rc=%s", addr(), strrc(rc)); + return rc; + } + + need_disconnect = false; + } else { + if (RC::SUCCESS != sql_result->return_code() || !sql_result->has_operator()) { + return write_state(event, need_disconnect); + } + + // send result set + // https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_com_query_response_text_resultset.html + RC rc = sql_result->open(); + if (rc != RC::SUCCESS) { + sql_result->set_return_code(rc); + return write_state(event, need_disconnect); + } + + // send metadata : Column Definition + rc = send_column_definition(sql_result, need_disconnect); + if (rc != RC::SUCCESS) { + return rc; + } + + rc = send_result_rows(sql_result, need_disconnect); + } + + return rc; +} + +RC MysqlCommunicator::send_packet(const BasePacket &packet) +{ + std::vector net_packet; + RC rc = packet.encode(client_capabilities_flag_, net_packet); + if (rc != RC::SUCCESS) { + LOG_WARN("failed to encode ok packet. rc=%s", strrc(rc)); + return rc; + } + + int ret = common::writen(fd_, net_packet.data(), net_packet.size()); + if (ret != 0) { + LOG_WARN("failed to send packet to client. addr=%s, error=%s", addr(), strerror(errno)); + return RC::IOERR; + } + + LOG_TRACE("send ok packet success. packet length=%d", net_packet.size()); + return rc; +} + +/** + * 发送列定义信息 + * https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_com_query_response_text_resultset.html + * https://mariadb.com/kb/en/result-set-packets/#column-definition-packet + * + * 先发送当前有多少个列 + * 然后发送N个包,告诉客户端每个列的信息 + */ +RC MysqlCommunicator::send_column_definition(SqlResult *sql_result, bool &need_disconnect) +{ + RC rc = RC::SUCCESS; + const TupleSchema &tuple_schema = sql_result->tuple_schema(); + const int cell_num = tuple_schema.cell_num(); + + std::vector net_packet; + net_packet.resize(1024); + char *buf = net_packet.data(); + int pos = 0; + + pos += 3; + store_int1(buf + pos, sequence_id_++); + pos += 1; + + if (client_capabilities_flag_ & CLIENT_OPTIONAL_RESULTSET_METADATA) { + store_int1(buf + pos, static_cast(ResultSetMetaData::RESULTSET_METADATA_FULL)); + pos += 1; + LOG_TRACE("client with optional resultset metadata"); + } else { + LOG_TRACE("client without optional resultset metadata"); + } + + pos += store_lenenc_int(buf + pos, cell_num); + + int payload_length = pos - 4; + store_int3(buf, payload_length); + net_packet.resize(pos); + + int ret = common::writen(fd_, net_packet.data(), net_packet.size()); + if (ret != 0){ + LOG_WARN("failed to send column count to client. addr=%s, error=%s", addr(), strerror(errno)); + need_disconnect = true; + return RC::IOERR; + } + + for (int i = 0; i < cell_num; i++) { + net_packet.resize(1024); + buf = net_packet.data(); + pos = 0; + + pos += 3; + store_int1(buf + pos, sequence_id_++); + pos += 1; + + const TupleCellSpec &spec = tuple_schema.cell_at(i); + const char *catalog = "def"; // The catalog used. Currently always "def" + const char *schema = "sys"; // schema name + const char *table = spec.table_name(); + const char *org_table = spec.table_name(); + const char *name = spec.alias(); + //const char *org_name = spec.field_name(); + const char *org_name = spec.alias(); + int fixed_len_fields = 0x0c; + int character_set = 33; + int column_length = 16384; + int type = MYSQL_TYPE_VAR_STRING; + int16_t flags = 0; + int8_t decimals = 0x1f; + + pos += store_lenenc_string(buf + pos, catalog); + pos += store_lenenc_string(buf + pos, schema); + pos += store_lenenc_string(buf + pos, table); + pos += store_lenenc_string(buf + pos, org_table); + pos += store_lenenc_string(buf + pos, name); + pos += store_lenenc_string(buf + pos, org_name); + pos += store_lenenc_int(buf + pos, fixed_len_fields); + store_int2(buf + pos, character_set); + pos += 2; + store_int4(buf + pos, column_length); + pos += 4; + store_int1(buf + pos, type); + pos += 1; + store_int2(buf + pos, flags); + pos += 2; + store_int1(buf + pos, decimals); + pos += 1; + store_int2(buf + pos, 0); // 按照mariadb的文档描述,最后还有一个unused字段int<2>,不过mysql的文档没有给出这样的描述 + pos += 2; + + payload_length = pos - 4; + store_int3(buf, payload_length); + net_packet.resize(pos); + + ret = common::writen(fd_, net_packet.data(), net_packet.size()); + if (ret != 0) { + LOG_WARN("failed to write column definition to client. addr=%s, error=%s", addr(), strerror(errno)); + need_disconnect = true; + return RC::IOERR; + } + } + + if (!(client_capabilities_flag_ & CLIENT_DEPRECATE_EOF)) { + EofPacket eof_packet; + eof_packet.packet_header.sequence_id = sequence_id_++; + eof_packet.status_flags = 0x02; + rc = send_packet(eof_packet); + if (rc != RC::SUCCESS) { + need_disconnect = true; + LOG_WARN("failed to send eof packet to client. addr=%s, error=%s", addr(), strerror(errno)); + } + } else { + LOG_TRACE("client use CLIENT_DEPRECATE_EOF"); + } + + LOG_TRACE("send column definition to client done"); + need_disconnect = false; + return RC::SUCCESS; +} + +/** + * 发送每行数据 + * 一行一个包 + */ +RC MysqlCommunicator::send_result_rows(SqlResult *sql_result, bool &need_disconnect) +{ + RC rc = RC::SUCCESS; + std::vector packet; + packet.resize(4 * 1024 * 1024); // TODO warning: length cannot be fix + + Tuple *tuple = nullptr; + while (RC::SUCCESS == (rc = sql_result->next_tuple(tuple))) { + // https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_com_query_response_text_resultset.html + // https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_com_query_response_text_resultset_row.html + // note: if some field is null, send a 0xFB + char *buf = packet.data(); + int pos = 0; + + pos += 3; + store_int1(buf + pos, sequence_id_++); + pos += 1; + + assert(tuple != nullptr); + const int cell_num = tuple->cell_num(); + TupleCell tuple_cell; + for (int i = 0; i < cell_num; i++) { + rc = tuple->cell_at(i, tuple_cell); + if (rc != RC::SUCCESS) { + sql_result->set_return_code(rc); + break; // TODO send error packet + } + + std::stringstream ss; + tuple_cell.to_string(ss); + pos += store_lenenc_string(buf + pos, ss.str().c_str()); + } + + int payload_length = pos - 4; + store_int3(buf, payload_length); + int ret = common::writen(fd_, buf, pos); + if (ret != 0) { + LOG_WARN("failed to send row packet to client. addr=%s, error=%s", addr(), strerror(errno)); + need_disconnect = true; + return RC::IOERR; + } + } + + // 所有行发送完成后,发送一个EOF或OK包 + if (client_capabilities_flag_ & CLIENT_DEPRECATE_EOF) { + LOG_TRACE("client has CLIENT_DEPRECATE_EOF, send ok packet"); + OkPacket ok_packet; + ok_packet.packet_header.sequence_id = sequence_id_++; + rc = send_packet(ok_packet); + } else { + EofPacket eof_packet; + eof_packet.packet_header.sequence_id = sequence_id_++; + rc = send_packet(eof_packet); + } + + LOG_TRACE("send rows to client done"); + need_disconnect = false; + return rc; +} diff --git a/src/observer/net/mysql_communicator.h b/src/observer/net/mysql_communicator.h new file mode 100644 index 0000000..d005626 --- /dev/null +++ b/src/observer/net/mysql_communicator.h @@ -0,0 +1,76 @@ +/* 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/11/22. +// + +#pragma once + +#include "net/communicator.h" + +class SqlResult; +class BasePacket; + +/** + * 与客户端通讯 + * 实现MySQL通讯协议 + * 可以参考 https://dev.mysql.com/doc/dev/mysql-server/latest/PAGE_PROTOCOL.html + * 或 mariadb文档 https://mariadb.com/kb/en/clientserver-protocol/ + */ +class MysqlCommunicator : public Communicator { +public: + + /** + * 连接刚开始建立时,进行一些初始化 + * 参考MySQL或MariaDB的手册,服务端要首先向客户端发送一个握手包,等客户端回复后, + * 再回复一个OkPacket或ErrPacket + */ + virtual RC init(int fd, Session *session, const std::string &addr) override; + + /** + * 有新的消息到达时,接收消息 + * 因为MySQL协议的特殊性,收到数据后不一定需要向后流转,比如握手包 + */ + virtual RC read_event(SessionEvent *&event) override; + + /** + * 将处理结果返回给客户端 + */ + virtual RC write_result(SessionEvent *event, bool &need_disconnect) override; + +private: + RC send_packet(const BasePacket &packet); + RC write_state(SessionEvent *event, bool &need_disconnect); + + /** + * 根据MySQL text protocol 描述,普通的结果分为列信息描述和行数据 + * 这里就分为两个函数 + */ + RC send_column_definition(SqlResult *sql_result, bool &need_disconnect); + RC send_result_rows(SqlResult *sql_result, bool &need_disconnect); + + /** + * 根据实际测试,客户端在连接上来时,会发起一个 version_comment的查询 + * 这里就针对这个查询返回一个结果 + */ + RC handle_version_comment(bool &need_disconnect); + +private: + //! 握手阶段(鉴权),需要做一些特殊处理,所以加个字段单独标记 + bool authed_ = false; + + //! 有时需要根据握手包中capabilities字段值的不同,而发送或接收不同的包 + uint32_t client_capabilities_flag_ = 0; + + //! 在一次通讯过程中(一个任务的请求与处理),每个包(packet)都有一个sequence id + //! 这个sequence id是递增的 + int8_t sequence_id_ = 0; +}; diff --git a/src/observer/net/server.cpp b/src/observer/net/server.cpp index e6c887f..009587f 100644 --- a/src/observer/net/server.cpp +++ b/src/observer/net/server.cpp @@ -35,6 +35,7 @@ See the Mulan PSL v2 for more details. */ #include "event/session_event.h" #include "session/session.h" #include "ini_setting.h" +#include "net/communicator.h" #include using namespace common; @@ -85,7 +86,6 @@ void Server::init() int Server::set_non_block(int fd) { - int flags = fcntl(fd, F_GETFL); if (flags == -1) { LOG_INFO("Failed to get flags of fd :%d. ", fd); @@ -100,87 +100,34 @@ int Server::set_non_block(int fd) return 0; } -void Server::close_connection(ConnectionContext *client_context) +void Server::close_connection(Communicator *communicator) { - LOG_INFO("Close connection of %s.", client_context->addr); - event_del(&client_context->read_event); - ::close(client_context->fd); - delete client_context->session; - client_context->session = nullptr; - delete client_context; + LOG_INFO("Close connection of %s.", communicator->addr()); + event_del(&communicator->read_event()); + delete communicator; } void Server::recv(int fd, short ev, void *arg) { - ConnectionContext *client = (ConnectionContext *)arg; - // Server::send(sev->getClient(), sev->getRequestBuf(), strlen(sev->getRequestBuf())); - - int data_len = 0; - int read_len = 0; - int buf_size = sizeof(client->buf); - memset(client->buf, 0, buf_size); - - TimerStat timer_stat(*read_socket_metric_); - MUTEX_LOCK(&client->mutex); - // 持续接收消息,直到遇到'\0'。将'\0'遇到的后续数据直接丢弃没有处理,因为目前仅支持一收一发的模式 - while (true) { - read_len = ::read(client->fd, client->buf + data_len, buf_size - data_len); - if (read_len < 0) { - if (errno == EAGAIN) { - continue; - } - break; - } - if (read_len == 0) { - break; - } - - if (read_len + data_len > buf_size) { - data_len += read_len; - break; - } - - bool msg_end = false; - for (int i = 0; i < read_len; i++) { - if (client->buf[data_len + i] == 0) { - data_len += i + 1; - msg_end = true; - break; - } - } - - if (msg_end) { - break; - } - - data_len += read_len; - } - - MUTEX_UNLOCK(&client->mutex); - timer_stat.end(); + Communicator *comm = (Communicator *)arg; - if (data_len > buf_size) { - LOG_WARN("The length of sql exceeds the limitation %d\n", buf_size); - close_connection(client); + SessionEvent *event = nullptr; + RC rc = comm->read_event(event); + if (rc != RC::SUCCESS) { + close_connection(comm); return; } - if (read_len == 0) { - LOG_INFO("The peer has been closed %s\n", client->addr); - close_connection(client); - return; - } else if (read_len < 0) { - LOG_ERROR("Failed to read socket of %s, %s\n", client->addr, strerror(errno)); - close_connection(client); + + if (event == nullptr) { + LOG_WARN("event is null while read event return success"); return; } - - LOG_INFO("receive command(size=%d): %s", data_len, client->buf); - SessionEvent *sev = new SessionEvent(client); - session_stage_->add_event(sev); + session_stage_->add_event(event); } +#if 0 // 这个函数仅负责发送数据,至于是否是一个完整的消息,由调用者控制 -int Server::send(ConnectionContext *client, const char *buf, int data_len) +int Server::send( *client, const char *buf, int data_len) { if (buf == nullptr || data_len == 0) { return 0; @@ -188,7 +135,6 @@ int Server::send(ConnectionContext *client, const char *buf, int data_len) TimerStat writeStat(*write_socket_metric_); - MUTEX_LOCK(&client->mutex); int ret = common::writen(client->fd, buf, data_len); if (ret < 0) { LOG_ERROR("Failed to send data back to client. ret=%d, error=%s", ret, strerror(errno)); @@ -198,9 +144,9 @@ int Server::send(ConnectionContext *client, const char *buf, int data_len) return -STATUS_FAILED_NETWORK; } - MUTEX_UNLOCK(&client->mutex); return 0; } +#endif void Server::accept(int fd, short ev, void *arg) { @@ -244,33 +190,32 @@ void Server::accept(int fd, short ev, void *arg) } } - ConnectionContext *client_context = new ConnectionContext(); - memset(client_context, 0, sizeof(ConnectionContext)); - client_context->fd = client_fd; - snprintf(client_context->addr, sizeof(client_context->addr), "%s", addr_str.c_str()); - pthread_mutex_init(&client_context->mutex, nullptr); + Communicator *communicator = instance->communicator_factory_.create(instance->server_param_.protocol); + RC rc = communicator->init(client_fd, new Session(Session::default_session()), addr_str); + if (rc != RC::SUCCESS) { + LOG_WARN("failed to init communicator. rc=%s", strrc(rc)); + delete communicator; + return; + } - event_set(&client_context->read_event, client_context->fd, EV_READ | EV_PERSIST, recv, client_context); + event_set(&communicator->read_event(), client_fd, EV_READ | EV_PERSIST, recv, communicator); - ret = event_base_set(instance->event_base_, &client_context->read_event); + ret = event_base_set(instance->event_base_, &communicator->read_event()); if (ret < 0) { - LOG_ERROR( - "Failed to do event_base_set for read event of %s into libevent, %s", client_context->addr, strerror(errno)); - delete client_context; - ::close(instance->server_socket_); + LOG_ERROR("Failed to do event_base_set for read event of %s into libevent, %s", + communicator->addr(), strerror(errno)); + delete communicator; return; } - ret = event_add(&client_context->read_event, nullptr); + ret = event_add(&communicator->read_event(), nullptr); if (ret < 0) { - LOG_ERROR("Failed to event_add for read event of %s into libevent, %s", client_context->addr, strerror(errno)); - delete client_context; - ::close(instance->server_socket_); + LOG_ERROR("Failed to event_add for read event of %s into libevent, %s", communicator->addr(), strerror(errno)); + delete communicator; return; } - client_context->session = new Session(Session::default_session()); - LOG_INFO("Accepted connection from %s\n", client_context->addr); + LOG_INFO("Accepted connection from %s\n", communicator->addr()); } int Server::start() diff --git a/src/observer/net/server.h b/src/observer/net/server.h index 82efbd5..01d87f7 100644 --- a/src/observer/net/server.h +++ b/src/observer/net/server.h @@ -12,15 +12,15 @@ See the Mulan PSL v2 for more details. */ // Created by Longda on 2021/4/1. // -#ifndef __OBSERVER_NET_SERVER_H__ -#define __OBSERVER_NET_SERVER_H__ +#pragma once #include "common/defs.h" #include "common/metrics/metrics.h" #include "common/seda/stage.h" -#include "net/connection_context.h" #include "net/server_param.h" +class Communicator; + class Server { public: Server(ServerParam input_server_param); @@ -28,7 +28,8 @@ public: public: static void init(); - static int send(ConnectionContext *client, const char *buf, int data_len); + // static int send(ConnectionContext *client, const char *buf, int data_len); + static void close_connection(Communicator *comm); public: int serve(); @@ -37,7 +38,6 @@ public: private: static void accept(int fd, short ev, void *arg); // close connection - static void close_connection(ConnectionContext *client_context); static void recv(int fd, short ev, void *arg); private: @@ -55,17 +55,9 @@ private: ServerParam server_param_; + CommunicatorFactory communicator_factory_; + static common::Stage *session_stage_; static common::SimpleTimer *read_socket_metric_; static common::SimpleTimer *write_socket_metric_; }; - -class Communicator { -public: - virtual ~Communicator() = default; - virtual int init(const ServerParam &server_param) = 0; - virtual int start() = 0; - virtual int stop() = 0; -}; - -#endif //__OBSERVER_NET_SERVER_H__ diff --git a/src/observer/net/server_param.h b/src/observer/net/server_param.h index aa0d012..90db4ec 100644 --- a/src/observer/net/server_param.h +++ b/src/observer/net/server_param.h @@ -12,10 +12,10 @@ See the Mulan PSL v2 for more details. */ // Created by Longda on 2021/4/13. // -#ifndef __SRC_OBSERVER_NET_SERVER_PARAM_H__ -#define __SRC_OBSERVER_NET_SERVER_PARAM_H__ +#pragma once #include +#include "net/communicator.h" class ServerParam { public: @@ -36,6 +36,6 @@ public: // 如果使用标准输入输出作为通信条件,就不再监听端口 bool use_unix_socket = false; -}; -#endif //__SRC_OBSERVER_NET_SERVER_PARAM_H__ + CommunicateProtocol protocol; +}; diff --git a/src/observer/session/session_stage.cpp b/src/observer/session/session_stage.cpp index 7639e20..c9e5c7c 100644 --- a/src/observer/session/session_stage.cpp +++ b/src/observer/session/session_stage.cpp @@ -27,6 +27,7 @@ See the Mulan PSL v2 for more details. */ #include "event/session_event.h" #include "event/sql_event.h" #include "net/server.h" +#include "net/communicator.h" #include "session/session.h" using namespace common; @@ -118,20 +119,14 @@ void SessionStage::callback_event(StageEvent *event, CallbackContext *context) return; } - const char *response = sev->get_response(); - int len = sev->get_response_len(); - if (len <= 0 || response == nullptr) { - response = "No data\n"; - len = strlen(response) + 1; - } - Server::send(sev->get_client(), response, len); - if ('\0' != response[len - 1]) { - // 这里强制性的给发送一个消息终结符,如果需要发送多条消息,需要调整 - char end = 0; - Server::send(sev->get_client(), &end, 1); + Communicator *communicator = sev->get_communicator(); + bool need_disconnect = false; + RC rc = communicator->write_result(sev, need_disconnect); + LOG_INFO("write result return %s", strrc(rc)); + if (need_disconnect) { + Server::close_connection(communicator); } - // sev->done(); LOG_TRACE("Exit\n"); return; } diff --git a/src/observer/session/session_stage.h b/src/observer/session/session_stage.h index 00136cc..206e99e 100644 --- a/src/observer/session/session_stage.h +++ b/src/observer/session/session_stage.h @@ -16,7 +16,6 @@ See the Mulan PSL v2 for more details. */ #define __OBSERVER_SESSION_SESSIONSTAGE_H__ #include "common/seda/stage.h" -#include "net/connection_context.h" #include "common/metrics/metrics.h" /** diff --git a/src/observer/sql/executor/execute_stage.cpp b/src/observer/sql/executor/execute_stage.cpp index a9fc784..484186c 100644 --- a/src/observer/sql/executor/execute_stage.cpp +++ b/src/observer/sql/executor/execute_stage.cpp @@ -32,6 +32,7 @@ See the Mulan PSL v2 for more details. */ #include "sql/operator/predicate_operator.h" #include "sql/operator/delete_operator.h" #include "sql/operator/project_operator.h" +#include "sql/operator/string_list_operator.h" #include "sql/stmt/stmt.h" #include "sql/stmt/select_stmt.h" #include "sql/stmt/update_stmt.h" @@ -200,18 +201,25 @@ void ExecuteStage::handle_request(common::StageEvent *event) do_clog_sync(sql_event); } case SCF_ROLLBACK: { - Trx *trx = session_event->get_client()->session->current_trx(); + Trx *trx = session_event->session()->current_trx(); RC rc = trx->rollback(); session->set_trx_multi_operation_mode(false); - session_event->set_response(strrc(rc)); + SqlResult *sql_result = new SqlResult; + sql_result->set_return_code(rc); + session_event->set_sql_result(sql_result); } break; case SCF_EXIT: { // do nothing - const char *response = "Unsupported\n"; - session_event->set_response(response); + SqlResult *sql_result = new SqlResult; + sql_result->set_return_code(RC::SUCCESS); + session_event->set_sql_result(sql_result); } break; default: { LOG_ERROR("Unsupported command=%d\n", sql->flag); + SqlResult *sql_result = new SqlResult; + sql_result->set_return_code(RC::UNIMPLENMENT); + sql_result->set_state_string("Unsupported command"); + session_event->set_sql_result(sql_result); } } } @@ -228,25 +236,6 @@ void end_trx_if_need(Session *session, Trx *trx, bool all_right) } } -void print_tuple_header(std::ostream &os, const ProjectOperator &oper) -{ - 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; @@ -409,15 +398,21 @@ RC ExecuteStage::do_select(SQLStageEvent *sql_event) 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); + SqlResult *sql_result = new SqlResult; + + PredicateOperator *pred_oper = new PredicateOperator(select_stmt->filter_stmt()); + pred_oper->add_child(scan_oper); + ProjectOperator *project_oper = new ProjectOperator; + project_oper->add_child(pred_oper); + TupleSchema schema; for (const Field &field : select_stmt->query_fields()) { - project_oper.add_projection(field.table(), field.meta()); + project_oper->add_projection(field.table(), field.meta()); + schema.append_cell(field.field_name()); } + sql_result->set_tuple_schema(schema); + sql_result->set_operator(project_oper); + + /* rc = project_oper.open(); if (rc != RC::SUCCESS) { LOG_WARN("failed to open operator"); @@ -447,21 +442,31 @@ RC ExecuteStage::do_select(SQLStageEvent *sql_event) rc = project_oper.close(); } session_event->set_response(ss.str()); + */ + session_event->set_sql_result(sql_result); return rc; } RC ExecuteStage::do_help(SQLStageEvent *sql_event) { SessionEvent *session_event = sql_event->session_event(); - 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); + const char *strings[] = { + "show tables;", + "desc `table name`;", + "create table `table name` (`column name` `column type`, ...);", + "create index `index name` on `table` (`column`);", + "insert into `table` values(`value1`,`value2`);", + "update `table` set column=value [where `column`=`value`];", + "delete from `table` [where `column`=`value`];", + "select [ * | `columns` ] from `table`;" + }; + StringListOperator *oper = new StringListOperator(); + for (size_t i = 0; i < sizeof(strings)/sizeof(strings[0]); i++) { + oper->append(strings[i]); + } + SqlResult *sql_result = new SqlResult; + sql_result->set_operator(oper); + session_event->set_sql_result(sql_result); return RC::SUCCESS; } @@ -472,44 +477,45 @@ RC ExecuteStage::do_create_table(SQLStageEvent *sql_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"); - } + SqlResult *sql_result = new SqlResult; + sql_result->set_return_code(rc); + sql_event->session_event()->set_sql_result(sql_result); return rc; } RC ExecuteStage::do_create_index(SQLStageEvent *sql_event) { + SqlResult *sql_result = new SqlResult; SessionEvent *session_event = sql_event->session_event(); + session_event->set_sql_result(sql_result); 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"); + sql_result->set_return_code(RC::SCHEMA_TABLE_NOT_EXIST); return RC::SCHEMA_TABLE_NOT_EXIST; } 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"); + sql_result->set_return_code(rc); return rc; } RC ExecuteStage::do_show_tables(SQLStageEvent *sql_event) { + SqlResult *sql_result = new SqlResult; SessionEvent *session_event = sql_event->session_event(); + session_event->set_sql_result(sql_result); Db *db = session_event->session()->get_current_db(); std::vector all_tables; 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()); + TupleSchema tuple_schema; + tuple_schema.append_cell(TupleCellSpec("", "Tables_in_SYS", "Tables_in_SYS")); + sql_result->set_tuple_schema(tuple_schema); + StringListOperator *oper = new StringListOperator; + for (const std::string &s : all_tables) { + oper->append(s); } + sql_result->set_operator(oper); return RC::SUCCESS; } @@ -519,13 +525,27 @@ RC ExecuteStage::do_desc_table(SQLStageEvent *sql_event) 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; + SqlResult *sql_result = new SqlResult; + sql_event->session_event()->set_sql_result(sql_result); if (table != nullptr) { - table->table_meta().desc(ss); + TupleSchema tuple_schema; + tuple_schema.append_cell(TupleCellSpec("", "Field", "Field")); + tuple_schema.append_cell(TupleCellSpec("", "Type", "Type")); + tuple_schema.append_cell(TupleCellSpec("", "Length", "Length")); + // TODO add Key + sql_result->set_tuple_schema(tuple_schema); + StringListOperator *oper = new StringListOperator; + const TableMeta &table_meta = table->table_meta(); + for (int i = table_meta.sys_field_num(); i < table_meta.field_num(); i++) { + const FieldMeta *field_meta = table_meta.field(i); + oper->append({field_meta->name(), attr_type_to_string(field_meta->type()), + std::to_string(field_meta->len())}); + } + sql_result->set_operator(oper); } else { - ss << "No such table: " << table_name << std::endl; + sql_result->set_return_code(RC::SCHEMA_TABLE_NOT_EXIST); + sql_result->set_state_string("Table not exists"); } - sql_event->session_event()->set_response(ss.str().c_str()); return RC::SUCCESS; } @@ -533,6 +553,8 @@ RC ExecuteStage::do_insert(SQLStageEvent *sql_event) { Stmt *stmt = sql_event->stmt(); SessionEvent *session_event = sql_event->session_event(); + SqlResult *sql_result = new SqlResult; + session_event->set_sql_result(sql_result); Session *session = session_event->session(); Db *db = session->get_current_db(); Trx *trx = session->current_trx(); @@ -552,23 +574,26 @@ RC ExecuteStage::do_insert(SQLStageEvent *sql_event) CLogRecord *clog_record = nullptr; rc = clog_manager->clog_gen_record(CLogType::REDO_MTR_COMMIT, trx->get_current_id(), clog_record); if (rc != RC::SUCCESS || clog_record == nullptr) { - session_event->set_response("FAILURE\n"); + if (rc == RC::SUCCESS) { + rc = RC::INTERNAL; + } + sql_result->set_return_code(rc); return rc; } rc = clog_manager->clog_append_record(clog_record); if (rc != RC::SUCCESS) { - session_event->set_response("FAILURE\n"); + sql_result->set_return_code(rc); return rc; } trx->next_current_id(); - session_event->set_response("SUCCESS\n"); + sql_result->set_return_code(RC::SUCCESS); } else { - session_event->set_response("SUCCESS\n"); + sql_result->set_return_code(RC::SUCCESS); } } else { - session_event->set_response("FAILURE\n"); + sql_result->set_return_code(rc); } return rc; } @@ -624,6 +649,8 @@ RC ExecuteStage::do_begin(SQLStageEvent *sql_event) { RC rc = RC::SUCCESS; SessionEvent *session_event = sql_event->session_event(); + SqlResult *sql_result = new SqlResult; + session_event->set_sql_result(sql_result); Session *session = session_event->session(); Db *db = session->get_current_db(); Trx *trx = session->current_trx(); @@ -634,16 +661,12 @@ RC ExecuteStage::do_begin(SQLStageEvent *sql_event) CLogRecord *clog_record = nullptr; rc = clog_manager->clog_gen_record(CLogType::REDO_MTR_BEGIN, trx->get_current_id(), clog_record); if (rc != RC::SUCCESS || clog_record == nullptr) { - session_event->set_response("FAILURE\n"); + sql_result->set_return_code(rc); return rc; } rc = clog_manager->clog_append_record(clog_record); - if (rc != RC::SUCCESS) { - session_event->set_response("FAILURE\n"); - } else { - session_event->set_response("SUCCESS\n"); - } + sql_result->set_return_code(rc); return rc; } @@ -652,6 +675,8 @@ RC ExecuteStage::do_commit(SQLStageEvent *sql_event) { RC rc = RC::SUCCESS; SessionEvent *session_event = sql_event->session_event(); + SqlResult *sql_result = new SqlResult; + session_event->set_sql_result(sql_result); Session *session = session_event->session(); Db *db = session->get_current_db(); Trx *trx = session->current_trx(); @@ -662,16 +687,12 @@ RC ExecuteStage::do_commit(SQLStageEvent *sql_event) CLogRecord *clog_record = nullptr; rc = clog_manager->clog_gen_record(CLogType::REDO_MTR_COMMIT, trx->get_current_id(), clog_record); if (rc != RC::SUCCESS || clog_record == nullptr) { - session_event->set_response("FAILURE\n"); + sql_result->set_return_code(rc); return rc; } rc = clog_manager->clog_append_record(clog_record); - if (rc != RC::SUCCESS) { - session_event->set_response("FAILURE\n"); - } else { - session_event->set_response("SUCCESS\n"); - } + sql_result->set_return_code(rc); trx->next_current_id(); @@ -681,16 +702,14 @@ RC ExecuteStage::do_commit(SQLStageEvent *sql_event) RC ExecuteStage::do_clog_sync(SQLStageEvent *sql_event) { RC rc = RC::SUCCESS; + SqlResult *sql_result = new SqlResult; SessionEvent *session_event = sql_event->session_event(); + session_event->set_sql_result(sql_result); Db *db = session_event->session()->get_current_db(); CLogManager *clog_manager = db->get_clog_manager(); rc = clog_manager->clog_sync(); - if (rc != RC::SUCCESS) { - session_event->set_response("FAILURE\n"); - } else { - session_event->set_response("SUCCESS\n"); - } + sql_result->set_return_code(rc); return rc; } diff --git a/src/observer/sql/executor/sql_result.cpp b/src/observer/sql/executor/sql_result.cpp new file mode 100644 index 0000000..408c6da --- /dev/null +++ b/src/observer/sql/executor/sql_result.cpp @@ -0,0 +1,48 @@ +/* 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/11/18. +// + +#include "rc.h" +#include "sql/executor/sql_result.h" + +void SqlResult::set_tuple_schema(const TupleSchema &schema) +{ + tuple_schema_ = schema; +} + +RC SqlResult::open() +{ + if (nullptr == operator_) { + return RC::INVALID_ARGUMENT; + } + return operator_->open(); +} + +RC SqlResult::close() +{ + if (nullptr == operator_) { + return RC::INVALID_ARGUMENT; + } + return operator_->close(); +} + +RC SqlResult::next_tuple(Tuple *&tuple) +{ + RC rc = operator_->next(); + if (rc != RC::SUCCESS) { + return rc; + } + + tuple = operator_->current_tuple(); + return rc; +} diff --git a/src/observer/sql/executor/sql_result.h b/src/observer/sql/executor/sql_result.h new file mode 100644 index 0000000..65ddfd8 --- /dev/null +++ b/src/observer/sql/executor/sql_result.h @@ -0,0 +1,49 @@ +/* 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/11/17. +// + +#pragma once + +#include +#include "sql/expr/tuple.h" +#include "sql/operator/operator.h" + +class SqlResult { +public: + SqlResult() = default; + ~SqlResult() + { + delete operator_; + operator_ = nullptr; + } + + void set_tuple_schema(const TupleSchema &schema); + void set_return_code(RC rc) { return_code_ = rc; } + void set_state_string(const std::string &state_string) { state_string_ = state_string; } + + void set_operator(Operator *oper) { operator_ = oper; } + bool has_operator() const { return operator_ != nullptr; } + const TupleSchema &tuple_schema() const { return tuple_schema_; } + RC return_code() const { return return_code_; } + const std::string &state_string() const { return state_string_; } + + RC open(); + RC close(); + RC next_tuple(Tuple *&tuple); + +private: + Operator *operator_ = nullptr; + TupleSchema tuple_schema_; + RC return_code_ = RC::SUCCESS; + std::string state_string_; +}; diff --git a/src/observer/sql/expr/expression.cpp b/src/observer/sql/expr/expression.cpp index ed6b450..a01b604 100644 --- a/src/observer/sql/expr/expression.cpp +++ b/src/observer/sql/expr/expression.cpp @@ -17,7 +17,7 @@ See the Mulan PSL v2 for more details. */ RC FieldExpr::get_value(const Tuple &tuple, TupleCell &cell) const { - return tuple.find_cell(field_, cell); + return tuple.find_cell(TupleCellSpec(table_name(), field_name()), cell); } RC ValueExpr::get_value(const Tuple &tuple, TupleCell & cell) const diff --git a/src/observer/sql/expr/expression.h b/src/observer/sql/expr/expression.h index 59b1750..12440ea 100644 --- a/src/observer/sql/expr/expression.h +++ b/src/observer/sql/expr/expression.h @@ -34,6 +34,7 @@ public: virtual RC get_value(const Tuple &tuple, TupleCell &cell) const = 0; virtual ExprType type() const = 0; + virtual AttrType value_type() const = 0; }; class FieldExpr : public Expression @@ -49,6 +50,10 @@ public: { return ExprType::FIELD; } + AttrType value_type() const override + { + return field_.attr_type(); + } Field &field() { @@ -94,6 +99,11 @@ public: return ExprType::VALUE; } + AttrType value_type() const override + { + return tuple_cell_.attr_type(); + } + void get_tuple_cell(TupleCell &cell) const { cell = tuple_cell_; } diff --git a/src/observer/sql/expr/tuple.h b/src/observer/sql/expr/tuple.h index dff7751..3be6996 100644 --- a/src/observer/sql/expr/tuple.h +++ b/src/observer/sql/expr/tuple.h @@ -25,38 +25,17 @@ See the Mulan PSL v2 for more details. */ class Table; -class TupleCellSpec +class TupleSchema { -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_; - } +public: + void append_cell(const TupleCellSpec &cell) { cells_.push_back(cell); } + void append_cell(const char *table, const char *field) { append_cell(TupleCellSpec(table, field)); } + void append_cell(const char *alias) { append_cell(TupleCellSpec(alias)); } + int cell_num() const { return static_cast(cells_.size()); } + const TupleCellSpec &cell_at(int i) const { return cells_[i]; } private: - const char *alias_ = nullptr; - Expression *expression_ = nullptr; + std::vector cells_; }; class Tuple @@ -67,9 +46,7 @@ public: 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; + virtual RC find_cell(const TupleCellSpec &spec, TupleCell &cell) const = 0; }; class RowTuple : public Tuple @@ -78,7 +55,7 @@ public: RowTuple() = default; virtual ~RowTuple() { - for (TupleCellSpec *spec : speces_) { + for (FieldExpr *spec : speces_) { delete spec; } speces_.clear(); @@ -94,7 +71,7 @@ public: table_ = table; this->speces_.reserve(fields->size()); for (const FieldMeta &field : *fields) { - speces_.push_back(new TupleCellSpec(new FieldExpr(table, &field))); + speces_.push_back(new FieldExpr(table, &field)); } } @@ -110,8 +87,7 @@ public: return RC::INVALID_ARGUMENT; } - const TupleCellSpec *spec = speces_[index]; - FieldExpr *field_expr = (FieldExpr *)spec->expression(); + FieldExpr *field_expr = speces_[index]; const FieldMeta *field_meta = field_expr->field().meta(); cell.set_type(field_meta->type()); cell.set_data(this->record_->data() + field_meta->offset()); @@ -119,16 +95,16 @@ public: return RC::SUCCESS; } - RC find_cell(const Field &field, TupleCell &cell) const override + RC find_cell(const TupleCellSpec &spec, TupleCell &cell) const override { - const char *table_name = field.table_name(); + const char *table_name = spec.table_name(); + const char *field_name = spec.field_name(); if (0 != strcmp(table_name, table_->name())) { return RC::NOTFOUND; } - const char *field_name = field.field_name(); for (size_t i = 0; i < speces_.size(); ++i) { - const FieldExpr * field_expr = (const FieldExpr *)speces_[i]->expression(); + const FieldExpr * field_expr = speces_[i]; const Field &field = field_expr->field(); if (0 == strcmp(field_name, field.field_name())) { return cell_at(i, cell); @@ -137,6 +113,7 @@ public: return RC::NOTFOUND; } + #if 0 RC cell_spec_at(int index, const TupleCellSpec *&spec) const override { if (index < 0 || index >= static_cast(speces_.size())) { @@ -146,6 +123,7 @@ public: spec = speces_[index]; return RC::SUCCESS; } + #endif Record &record() { @@ -159,20 +137,8 @@ public: private: Record *record_ = nullptr; const Table *table_ = nullptr; - std::vector 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 tuples_; + std::vector speces_; }; -*/ class ProjectTuple : public Tuple { @@ -210,13 +176,15 @@ public: } const TupleCellSpec *spec = speces_[index]; - return spec->expression()->get_value(*tuple_, cell); + return tuple_->find_cell(*spec, cell); } - RC find_cell(const Field &field, TupleCell &cell) const override + RC find_cell(const TupleCellSpec &spec, TupleCell &cell) const override { - return tuple_->find_cell(field, cell); + return tuple_->find_cell(spec, cell); } + + #if 0 RC cell_spec_at(int index, const TupleCellSpec *&spec) const override { if (index < 0 || index >= static_cast(speces_.size())) { @@ -225,7 +193,43 @@ public: spec = speces_[index]; return RC::SUCCESS; } + #endif private: std::vector speces_; Tuple *tuple_ = nullptr; }; + +class ValueListTuple : public Tuple +{ +public: + ValueListTuple() = default; + virtual ~ValueListTuple() = default; + + void set_cells(const std::vector &cells) + { + cells_ = cells; + } + + virtual int cell_num() const override + { + return static_cast(cells_.size()); + } + + virtual RC cell_at(int index, TupleCell &cell) const override + { + if (index < 0 || index >= cell_num()) { + return RC::NOTFOUND; + } + + cell = cells_[index]; + return RC::SUCCESS; + } + + virtual RC find_cell(const TupleCellSpec &spec, TupleCell &cell) const override + { + return RC::INTERNAL; + } + +private: + std::vector cells_; +}; diff --git a/src/observer/sql/expr/tuple_cell.cpp b/src/observer/sql/expr/tuple_cell.cpp index 8f527c4..485a7b1 100644 --- a/src/observer/sql/expr/tuple_cell.cpp +++ b/src/observer/sql/expr/tuple_cell.cpp @@ -18,6 +18,27 @@ See the Mulan PSL v2 for more details. */ #include "util/comparator.h" #include "util/util.h" +TupleCellSpec::TupleCellSpec(const char *table_name, const char *field_name, const char *alias) +{ + if (table_name) { + table_name_ = table_name; + } + if (field_name) { + field_name_ = field_name; + } + if (alias) { + alias_ = alias; + } +} + +TupleCellSpec::TupleCellSpec(const char *alias) +{ + if (alias) { + alias_ = alias; + } +} +//////////////////////////////////////////////////////////////////////////////// + void TupleCell::to_string(std::ostream &os) const { switch (attr_type_) { diff --git a/src/observer/sql/expr/tuple_cell.h b/src/observer/sql/expr/tuple_cell.h index faf3996..c53d66c 100644 --- a/src/observer/sql/expr/tuple_cell.h +++ b/src/observer/sql/expr/tuple_cell.h @@ -18,6 +18,22 @@ See the Mulan PSL v2 for more details. */ #include "storage/common/table.h" #include "storage/common/field_meta.h" +class TupleCellSpec +{ +public: + TupleCellSpec(const char *table_name, const char *field_name, const char *alias = nullptr); + TupleCellSpec(const char *alias); + + const char *table_name() const { return table_name_.c_str(); } + const char *field_name() const { return field_name_.c_str(); } + const char *alias() const { return alias_.c_str(); } + +private: + std::string table_name_; + std::string field_name_; + std::string alias_; +}; + class TupleCell { public: diff --git a/src/observer/sql/operator/delete_operator.h b/src/observer/sql/operator/delete_operator.h index 1e6171a..156c709 100644 --- a/src/observer/sql/operator/delete_operator.h +++ b/src/observer/sql/operator/delete_operator.h @@ -36,8 +36,6 @@ public: 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; Trx *trx_ = nullptr; diff --git a/src/observer/net/connection_context.h b/src/observer/sql/operator/operator.cpp similarity index 56% rename from src/observer/net/connection_context.h rename to src/observer/sql/operator/operator.cpp index 1f83afa..6f047a5 100644 --- a/src/observer/net/connection_context.h +++ b/src/observer/sql/operator/operator.cpp @@ -9,24 +9,14 @@ MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the Mulan PSL v2 for more details. */ // -// Created by Longda on 2021/4/13. +// Created by WangYunlai on 2022/11/18. // -#ifndef __SRC_OBSERVER_NET_CONNECTION_CONTEXT_H__ -#define __SRC_OBSERVER_NET_CONNECTION_CONTEXT_H__ +#include "sql/operator/operator.h" -#include -#include - -class Session; - -typedef struct _ConnectionContext { - Session *session; - int fd; - struct event read_event; - pthread_mutex_t mutex; - char addr[24]; - char buf[SOCKET_BUFFER_SIZE]; -} ConnectionContext; - -#endif //__SRC_OBSERVER_NET_CONNECTION_CONTEXT_H__ +Operator::~Operator() +{ + for (Operator *oper : children_) { + delete oper; + } +} diff --git a/src/observer/sql/operator/operator.h b/src/observer/sql/operator/operator.h index f9da28f..01bb400 100644 --- a/src/observer/sql/operator/operator.h +++ b/src/observer/sql/operator/operator.h @@ -9,7 +9,7 @@ MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the Mulan PSL v2 for more details. */ // -// Created by WangYunlai on 2021/6/7. +// Created by WangYunlai on 2022/6/7. // #pragma once @@ -27,15 +27,13 @@ public: Operator() {} - virtual ~Operator() = default; + virtual ~Operator(); 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); diff --git a/src/observer/sql/operator/predicate_operator.cpp b/src/observer/sql/operator/predicate_operator.cpp index c9befd3..c914db1 100644 --- a/src/observer/sql/operator/predicate_operator.cpp +++ b/src/observer/sql/operator/predicate_operator.cpp @@ -105,12 +105,3 @@ bool PredicateOperator::do_predicate(RowTuple &tuple) } 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); -// } diff --git a/src/observer/sql/operator/predicate_operator.h b/src/observer/sql/operator/predicate_operator.h index f92b486..e108d26 100644 --- a/src/observer/sql/operator/predicate_operator.h +++ b/src/observer/sql/operator/predicate_operator.h @@ -36,8 +36,6 @@ public: 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: diff --git a/src/observer/sql/operator/project_operator.cpp b/src/observer/sql/operator/project_operator.cpp index ed9ea62..f1b51fa 100644 --- a/src/observer/sql/operator/project_operator.cpp +++ b/src/observer/sql/operator/project_operator.cpp @@ -54,12 +54,6 @@ void ProjectOperator::add_projection(const Table *table, const FieldMeta *field_ { // 对单表来说,展示的(alias) 字段总是字段名称, // 对多表查询来说,展示的alias 需要带表名字 - TupleCellSpec *spec = new TupleCellSpec(new FieldExpr(table, field_meta)); - spec->set_alias(field_meta->name()); + TupleCellSpec *spec = new TupleCellSpec(table->name(), field_meta->name(), 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); -} diff --git a/src/observer/sql/operator/project_operator.h b/src/observer/sql/operator/project_operator.h index b0fefea..d1c8590 100644 --- a/src/observer/sql/operator/project_operator.h +++ b/src/observer/sql/operator/project_operator.h @@ -36,8 +36,6 @@ public: return tuple_.cell_num(); } - RC tuple_cell_spec_at(int index, const TupleCellSpec *&spec) const; - Tuple * current_tuple() override; private: ProjectTuple tuple_; diff --git a/src/observer/sql/operator/string_list_operator.h b/src/observer/sql/operator/string_list_operator.h new file mode 100644 index 0000000..923d98b --- /dev/null +++ b/src/observer/sql/operator/string_list_operator.h @@ -0,0 +1,89 @@ +/* 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/11/18. +// + +#pragma once + +#include + +class StringListOperator : public Operator +{ +public: + StringListOperator() + {} + + virtual ~StringListOperator() = default; + + template + void append(InputIt begin, InputIt end) + { + strings_.emplace_back(begin, end); + } + + void append(std::initializer_list init) + { + strings_.emplace_back(init); + } + + template + void append( const T &v) + { + strings_.emplace_back(1, v); + } + + RC open() override + { + return RC::SUCCESS; + } + + RC next() override + { + if (!started_) { + started_ = true; + iterator_ = strings_.begin(); + } else if (iterator_ != strings_.end()) { + ++iterator_; + } + return iterator_ == strings_.end() ? RC::RECORD_EOF : RC::SUCCESS; + } + virtual RC close() override + { + iterator_ = strings_.end(); + return RC::SUCCESS; + } + + virtual Tuple * current_tuple() override + { + if (iterator_ == strings_.end()) { + return nullptr; + } + + const StringList &string_list = *iterator_; + std::vector cells; + for (const std::string &s : string_list) { + + TupleCell cell(CHARS, const_cast(s.data())); + cell.set_length(s.length()); + cells.push_back(cell); + } + tuple_.set_cells(cells); + return &tuple_; + } +private: + using StringList = std::vector; + using StringListList = std::vector; + StringListList strings_; + StringListList::iterator iterator_; + bool started_ = false; + ValueListTuple tuple_; +}; diff --git a/src/observer/sql/operator/table_scan_operator.h b/src/observer/sql/operator/table_scan_operator.h index a240149..a0bccb9 100644 --- a/src/observer/sql/operator/table_scan_operator.h +++ b/src/observer/sql/operator/table_scan_operator.h @@ -9,7 +9,7 @@ MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the Mulan PSL v2 for more details. */ // -// Created by WangYunlai on 2021/6/7. +// Created by WangYunlai on 2022/6/7. // #pragma once @@ -35,12 +35,6 @@ public: 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_; diff --git a/src/observer/sql/parser/parse.cpp b/src/observer/sql/parser/parse.cpp index e7fb20e..377a79d 100644 --- a/src/observer/sql/parser/parse.cpp +++ b/src/observer/sql/parser/parse.cpp @@ -19,14 +19,14 @@ See the Mulan PSL v2 for more details. */ RC parse(char *st, Query *sqln); -void relation_attr_init(RelAttr *relation_attr, const char *relation_name, const char *attribute_name) +void relation_attr_init(RelAttr *relation_attr, char *relation_name, char *attribute_name) { if (relation_name != nullptr) { - relation_attr->relation_name = strdup(relation_name); + relation_attr->relation_name = relation_name; } else { relation_attr->relation_name = nullptr; } - relation_attr->attribute_name = strdup(attribute_name); + relation_attr->attribute_name = attribute_name; } void relation_attr_destroy(RelAttr *relation_attr) @@ -49,6 +49,11 @@ void value_init_float(Value *value, float v) value->data = malloc(sizeof(v)); memcpy(value->data, &v, sizeof(v)); } +void value_init_string(Value *value, char *v) +{ + value->type = CHARS; + value->data = v; +} void value_init_string(Value *value, const char *v) { value->type = CHARS; @@ -93,9 +98,9 @@ void condition_destroy(Condition *condition) } } -void attr_info_init(AttrInfo *attr_info, const char *name, AttrType type, size_t length) +void attr_info_init(AttrInfo *attr_info, char *name, AttrType type, size_t length) { - attr_info->name = strdup(name); + attr_info->name = name; attr_info->type = type; attr_info->length = length; } @@ -110,9 +115,9 @@ void selects_append_attribute(Selects *selects, RelAttr *rel_attr) { selects->attributes[selects->attr_num++] = *rel_attr; } -void selects_append_relation(Selects *selects, const char *relation_name) +void selects_append_relation(Selects *selects, char *relation_name) { - selects->relations[selects->relation_num++] = strdup(relation_name); + selects->relations[selects->relation_num++] = relation_name; } void selects_append_conditions(Selects *selects, Condition conditions[], size_t condition_num) @@ -143,11 +148,11 @@ void selects_destroy(Selects *selects) selects->condition_num = 0; } -void inserts_init(Inserts *inserts, const char *relation_name, Value values[], size_t value_num) +void inserts_init(Inserts *inserts, char *relation_name, Value values[], size_t value_num) { assert(value_num <= sizeof(inserts->values) / sizeof(inserts->values[0])); - inserts->relation_name = strdup(relation_name); + inserts->relation_name = relation_name; for (size_t i = 0; i < value_num; i++) { inserts->values[i] = values[i]; } @@ -164,9 +169,9 @@ void inserts_destroy(Inserts *inserts) inserts->value_num = 0; } -void deletes_init_relation(Deletes *deletes, const char *relation_name) +void deletes_init_relation(Deletes *deletes, char *relation_name) { - deletes->relation_name = strdup(relation_name); + deletes->relation_name = relation_name; } void deletes_set_conditions(Deletes *deletes, Condition conditions[], size_t condition_num) @@ -187,11 +192,11 @@ void deletes_destroy(Deletes *deletes) deletes->relation_name = nullptr; } -void updates_init(Updates *updates, const char *relation_name, const char *attribute_name, Value *value, +void updates_init(Updates *updates, char *relation_name, char *attribute_name, Value *value, Condition conditions[], size_t condition_num) { - updates->relation_name = strdup(relation_name); - updates->attribute_name = strdup(attribute_name); + updates->relation_name = relation_name; + updates->attribute_name = attribute_name; updates->value = *value; assert(condition_num <= sizeof(updates->conditions) / sizeof(updates->conditions[0])); @@ -221,9 +226,9 @@ void create_table_append_attribute(CreateTable *create_table, AttrInfo *attr_inf create_table->attributes[create_table->attribute_count++] = *attr_info; } -void create_table_init_name(CreateTable *create_table, const char *relation_name) +void create_table_init_name(CreateTable *create_table, char *relation_name) { - create_table->relation_name = strdup(relation_name); + create_table->relation_name = relation_name; } void create_table_destroy(CreateTable *create_table) @@ -236,9 +241,9 @@ void create_table_destroy(CreateTable *create_table) create_table->relation_name = nullptr; } -void drop_table_init(DropTable *drop_table, const char *relation_name) +void drop_table_init(DropTable *drop_table, char *relation_name) { - drop_table->relation_name = strdup(relation_name); + drop_table->relation_name = relation_name; } void drop_table_destroy(DropTable *drop_table) @@ -248,11 +253,11 @@ void drop_table_destroy(DropTable *drop_table) } void create_index_init( - CreateIndex *create_index, const char *index_name, const char *relation_name, const char *attr_name) + CreateIndex *create_index, char *index_name, char *relation_name, char *attr_name) { - create_index->index_name = strdup(index_name); - create_index->relation_name = strdup(relation_name); - create_index->attribute_name = strdup(attr_name); + create_index->index_name = index_name; + create_index->relation_name = relation_name; + create_index->attribute_name = attr_name; } void create_index_destroy(CreateIndex *create_index) @@ -266,9 +271,9 @@ void create_index_destroy(CreateIndex *create_index) create_index->attribute_name = nullptr; } -void drop_index_init(DropIndex *drop_index, const char *index_name) +void drop_index_init(DropIndex *drop_index, char *index_name) { - drop_index->index_name = strdup(index_name); + drop_index->index_name = index_name; } void drop_index_destroy(DropIndex *drop_index) @@ -277,9 +282,9 @@ void drop_index_destroy(DropIndex *drop_index) drop_index->index_name = nullptr; } -void desc_table_init(DescTable *desc_table, const char *relation_name) +void desc_table_init(DescTable *desc_table, char *relation_name) { - desc_table->relation_name = strdup(relation_name); + desc_table->relation_name = relation_name; } void desc_table_destroy(DescTable *desc_table) @@ -288,14 +293,14 @@ void desc_table_destroy(DescTable *desc_table) desc_table->relation_name = nullptr; } -void load_data_init(LoadData *load_data, const char *relation_name, const char *file_name) +void load_data_init(LoadData *load_data, char *relation_name, char *file_name) { - load_data->relation_name = strdup(relation_name); + load_data->relation_name = relation_name; if (file_name[0] == '\'' || file_name[0] == '\"') { file_name++; } - char *dup_file_name = strdup(file_name); + char *dup_file_name = file_name; int len = strlen(dup_file_name); if (dup_file_name[len - 1] == '\'' || dup_file_name[len - 1] == '\"') { dup_file_name[len - 1] = 0; @@ -386,6 +391,25 @@ void query_destroy(Query *query) free(query); } +const char *ATTR_TYPE_NAME[] = {"undefined", "chars", "ints", "floats"}; + +const char *attr_type_to_string(AttrType type) +{ + if (type >= UNDEFINED && type <= FLOATS) { + return ATTR_TYPE_NAME[type]; + } + return "unknown"; +} +AttrType attr_type_from_string(const char *s) +{ + for (unsigned int i = 0; i < sizeof(ATTR_TYPE_NAME) / sizeof(ATTR_TYPE_NAME[0]); i++) { + if (0 == strcmp(ATTR_TYPE_NAME[i], s)) { + return (AttrType)i; + } + } + return UNDEFINED; +} + //////////////////////////////////////////////////////////////////////////////// int sql_parse(const char *st, Query *sqls); diff --git a/src/observer/sql/parser/parse_defs.h b/src/observer/sql/parser/parse_defs.h index c2ffc4d..1007b30 100644 --- a/src/observer/sql/parser/parse_defs.h +++ b/src/observer/sql/parser/parse_defs.h @@ -12,8 +12,7 @@ See the Mulan PSL v2 for more details. */ // Created by Meiyi // -#ifndef __OBSERVER_SQL_PARSER_PARSE_DEFS_H__ -#define __OBSERVER_SQL_PARSER_PARSE_DEFS_H__ +#pragma once #include @@ -180,11 +179,12 @@ typedef struct Query { union Queries sstr; } Query; -void relation_attr_init(RelAttr *relation_attr, const char *relation_name, const char *attribute_name); +void relation_attr_init(RelAttr *relation_attr, char *relation_name, char *attribute_name); void relation_attr_destroy(RelAttr *relation_attr); void value_init_integer(Value *value, int v); void value_init_float(Value *value, float v); +void value_init_string(Value *value, char *v); void value_init_string(Value *value, const char *v); void value_destroy(Value *value); @@ -192,44 +192,44 @@ void condition_init(Condition *condition, CompOp comp, int left_is_attr, RelAttr int right_is_attr, RelAttr *right_attr, Value *right_value); void condition_destroy(Condition *condition); -void attr_info_init(AttrInfo *attr_info, const char *name, AttrType type, size_t length); +void attr_info_init(AttrInfo *attr_info, char *name, AttrType type, size_t length); void attr_info_destroy(AttrInfo *attr_info); void selects_init(Selects *selects, ...); void selects_append_attribute(Selects *selects, RelAttr *rel_attr); -void selects_append_relation(Selects *selects, const char *relation_name); +void selects_append_relation(Selects *selects, char *relation_name); void selects_append_conditions(Selects *selects, Condition conditions[], size_t condition_num); void selects_destroy(Selects *selects); -void inserts_init(Inserts *inserts, const char *relation_name, Value values[], size_t value_num); +void inserts_init(Inserts *inserts, char *relation_name, Value values[], size_t value_num); void inserts_destroy(Inserts *inserts); -void deletes_init_relation(Deletes *deletes, const char *relation_name); +void deletes_init_relation(Deletes *deletes, char *relation_name); void deletes_set_conditions(Deletes *deletes, Condition conditions[], size_t condition_num); void deletes_destroy(Deletes *deletes); -void updates_init(Updates *updates, const char *relation_name, const char *attribute_name, Value *value, +void updates_init(Updates *updates, char *relation_name, char *attribute_name, Value *value, Condition conditions[], size_t condition_num); void updates_destroy(Updates *updates); void create_table_append_attribute(CreateTable *create_table, AttrInfo *attr_info); -void create_table_init_name(CreateTable *create_table, const char *relation_name); +void create_table_init_name(CreateTable *create_table, char *relation_name); void create_table_destroy(CreateTable *create_table); -void drop_table_init(DropTable *drop_table, const char *relation_name); +void drop_table_init(DropTable *drop_table, char *relation_name); void drop_table_destroy(DropTable *drop_table); void create_index_init( - CreateIndex *create_index, const char *index_name, const char *relation_name, const char *attr_name); + CreateIndex *create_index, char *index_name, char *relation_name, char *attr_name); void create_index_destroy(CreateIndex *create_index); -void drop_index_init(DropIndex *drop_index, const char *index_name); +void drop_index_init(DropIndex *drop_index, char *index_name); void drop_index_destroy(DropIndex *drop_index); -void desc_table_init(DescTable *desc_table, const char *relation_name); +void desc_table_init(DescTable *desc_table, char *relation_name); void desc_table_destroy(DescTable *desc_table); -void load_data_init(LoadData *load_data, const char *relation_name, const char *file_name); +void load_data_init(LoadData *load_data, char *relation_name, char *file_name); void load_data_destroy(LoadData *load_data); void query_init(Query *query); @@ -237,4 +237,5 @@ Query *query_create(); // create and init void query_reset(Query *query); void query_destroy(Query *query); // reset and delete -#endif // __OBSERVER_SQL_PARSER_PARSE_DEFS_H__ +const char *attr_type_to_string(AttrType type); +AttrType attr_type_from_string(const char *s); diff --git a/src/observer/sql/parser/parse_stage.cpp b/src/observer/sql/parser/parse_stage.cpp index 0ca9c90..7684a7e 100644 --- a/src/observer/sql/parser/parse_stage.cpp +++ b/src/observer/sql/parser/parse_stage.cpp @@ -129,10 +129,13 @@ RC ParseStage::handle_request(StageEvent *event) return RC::INTERNAL; } + SqlResult *sql_result = new SqlResult; RC ret = parse(sql.c_str(), query_result); if (ret != RC::SUCCESS) { // set error information to event - sql_event->session_event()->set_response("Failed to parse sql\n"); + sql_result->set_return_code(ret); + sql_result->set_state_string("Failed to parse sql"); + sql_event->session_event()->set_sql_result(sql_result); query_destroy(query_result); return RC::INTERNAL; } diff --git a/src/observer/sql/parser/resolve_stage.cpp b/src/observer/sql/parser/resolve_stage.cpp index fa3f8d3..bcc5c63 100644 --- a/src/observer/sql/parser/resolve_stage.cpp +++ b/src/observer/sql/parser/resolve_stage.cpp @@ -106,7 +106,9 @@ void ResolveStage::handle_event(StageEvent *event) 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"); + SqlResult *sql_result = new SqlResult; + sql_result->set_return_code(rc); + session_event->set_sql_result(sql_result); return; } diff --git a/src/observer/sql/parser/yacc_sql.cpp b/src/observer/sql/parser/yacc_sql.cpp index d8bb4b5..c8ecd79 100644 --- a/src/observer/sql/parser/yacc_sql.cpp +++ b/src/observer/sql/parser/yacc_sql.cpp @@ -88,7 +88,7 @@ typedef struct ParserContext { Value values[MAX_NUM]; Condition conditions[MAX_NUM]; CompOp comp; - char id[MAX_NUM]; + char id[MAX_NUM]; } ParserContext; //获取子串 @@ -222,21 +222,20 @@ enum yysymbol_kind_t YYSYMBOL_attr_def = 67, /* attr_def */ YYSYMBOL_number = 68, /* number */ YYSYMBOL_type = 69, /* type */ - YYSYMBOL_ID_get = 70, /* ID_get */ - YYSYMBOL_insert = 71, /* insert */ - YYSYMBOL_value_list = 72, /* value_list */ - YYSYMBOL_value = 73, /* value */ - YYSYMBOL_delete = 74, /* delete */ - YYSYMBOL_update = 75, /* update */ - YYSYMBOL_select = 76, /* select */ - YYSYMBOL_select_attr = 77, /* select_attr */ - YYSYMBOL_attr_list = 78, /* attr_list */ - YYSYMBOL_rel_list = 79, /* rel_list */ - YYSYMBOL_where = 80, /* where */ - YYSYMBOL_condition_list = 81, /* condition_list */ - YYSYMBOL_condition = 82, /* condition */ - YYSYMBOL_comOp = 83, /* comOp */ - YYSYMBOL_load_data = 84 /* load_data */ + YYSYMBOL_insert = 70, /* insert */ + YYSYMBOL_value_list = 71, /* value_list */ + YYSYMBOL_value = 72, /* value */ + YYSYMBOL_delete = 73, /* delete */ + YYSYMBOL_update = 74, /* update */ + YYSYMBOL_select = 75, /* select */ + YYSYMBOL_select_attr = 76, /* select_attr */ + YYSYMBOL_attr_list = 77, /* attr_list */ + YYSYMBOL_rel_list = 78, /* rel_list */ + YYSYMBOL_where = 79, /* where */ + YYSYMBOL_condition_list = 80, /* condition_list */ + YYSYMBOL_condition = 81, /* condition */ + YYSYMBOL_comOp = 82, /* comOp */ + YYSYMBOL_load_data = 83 /* load_data */ }; typedef enum yysymbol_kind_t yysymbol_kind_t; @@ -546,16 +545,16 @@ union yyalloc /* YYFINAL -- State number of the termination state. */ #define YYFINAL 2 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 148 +#define YYLAST 150 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 51 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 34 +#define YYNNTS 33 /* YYNRULES -- Number of rules. */ -#define YYNRULES 76 +#define YYNRULES 75 /* YYNSTATES -- Number of states. */ -#define YYNSTATES 162 +#define YYNSTATES 161 /* YYMAXUTOK -- Last valid token kind. */ #define YYMAXUTOK 305 @@ -613,10 +612,10 @@ static const yytype_int16 yyrline[] = 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 158, 163, 168, 174, 180, 186, 192, 198, 204, 211, 219, 226, 234, 236, 240, 247, 256, 259, 260, - 261, 264, 273, 282, 284, 289, 292, 295, 302, 312, - 322, 339, 344, 349, 355, 357, 362, 369, 371, 375, - 377, 381, 383, 388, 399, 408, 419, 429, 439, 450, - 464, 465, 466, 467, 468, 469, 473 + 261, 264, 273, 275, 280, 283, 286, 294, 304, 314, + 331, 336, 341, 347, 349, 354, 361, 363, 367, 369, + 373, 375, 380, 391, 400, 411, 421, 431, 442, 456, + 457, 458, 459, 460, 461, 465 }; #endif @@ -641,10 +640,10 @@ static const char *const yytname[] = "FLOAT", "ID", "PATH", "SSS", "STAR", "STRING_V", "$accept", "commands", "command", "exit", "help", "sync", "begin", "commit", "rollback", "drop_table", "show_tables", "desc_table", "create_index", "drop_index", - "create_table", "attr_def_list", "attr_def", "number", "type", "ID_get", - "insert", "value_list", "value", "delete", "update", "select", - "select_attr", "attr_list", "rel_list", "where", "condition_list", - "condition", "comOp", "load_data", YY_NULLPTR + "create_table", "attr_def_list", "attr_def", "number", "type", "insert", + "value_list", "value", "delete", "update", "select", "select_attr", + "attr_list", "rel_list", "where", "condition_list", "condition", "comOp", + "load_data", YY_NULLPTR }; static const char * @@ -668,7 +667,7 @@ static const yytype_int16 yytoknum[] = }; #endif -#define YYPACT_NINF (-95) +#define YYPACT_NINF (-94) #define yypact_value_is_default(Yyn) \ ((Yyn) == YYPACT_NINF) @@ -682,23 +681,23 @@ static const yytype_int16 yytoknum[] = STATE-NUM. */ static const yytype_int16 yypact[] = { - -95, 5, -95, 78, 79, 31, -40, 0, 8, -1, - -7, -14, 39, 40, 53, 54, 64, 26, -95, -95, - -95, -95, -95, -95, -95, -95, -95, -95, -95, -95, - -95, -95, -95, -95, -95, -95, 33, 42, 43, 44, - -6, -95, 61, 69, 89, -95, 47, 48, 62, -95, - -95, -95, -95, -95, 60, 80, 65, 95, 97, 55, - 56, -95, 57, -95, -95, 75, 74, 63, 58, 66, - 67, -95, -95, -5, 90, 92, 91, 15, 108, 76, - 87, -95, 98, 59, 101, 72, -95, -95, 73, 74, - -10, -95, -95, 6, -95, 12, 88, -95, -10, 115, - 66, 105, -95, -95, -95, 107, 81, 90, 92, 121, - 110, 83, -95, -95, -95, -95, -95, -95, 20, 25, - 15, -95, 74, 84, 98, 122, 82, 114, -95, -95, - -95, -10, 116, 12, -95, -95, 109, -95, 88, 129, - 131, -95, -95, -95, 118, 134, 110, 135, 30, 93, - -95, -95, -95, -95, -95, -95, -95, 113, -95, -95, - 96, -95 + -94, 5, -94, 26, 83, 36, -40, 0, 8, -1, + -7, -10, 39, 40, 53, 54, 59, 2, -94, -94, + -94, -94, -94, -94, -94, -94, -94, -94, -94, -94, + -94, -94, -94, -94, -94, -94, 21, 31, 38, 44, + -6, -94, 42, 78, 89, -94, 47, 48, 62, -94, + -94, -94, -94, -94, 60, 80, 65, 95, 97, 55, + 56, -94, 57, -94, -94, 75, 74, 61, 58, 63, + 66, -94, -94, -5, 90, 92, 98, 15, 108, 77, + 85, 64, 99, 100, 72, -94, -94, 73, 74, 35, + -94, -94, 6, -94, 12, 88, -94, 35, 115, -94, + -94, -94, 106, 63, 107, 79, 90, 92, 120, 109, + 82, -94, -94, -94, -94, -94, -94, 20, 25, 15, + -94, 74, 84, 87, 99, 123, 112, -94, -94, -94, + 35, 116, 12, -94, -94, 105, -94, 88, 131, 132, + -94, 119, -94, -94, 134, 109, 135, 30, 93, -94, + -94, -94, -94, -94, -94, -94, 113, -94, -94, 96, + -94 }; /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. @@ -710,37 +709,37 @@ static const yytype_int8 yydefact[] = 0, 0, 0, 0, 0, 0, 0, 0, 3, 20, 19, 14, 15, 16, 17, 9, 10, 11, 12, 13, 8, 5, 7, 6, 4, 18, 0, 0, 0, 0, - 54, 51, 0, 0, 0, 23, 0, 0, 0, 24, + 53, 50, 0, 0, 0, 23, 0, 0, 0, 24, 25, 26, 22, 21, 0, 0, 0, 0, 0, 0, - 0, 52, 0, 29, 28, 0, 59, 0, 0, 0, - 0, 27, 31, 54, 54, 57, 0, 0, 0, 0, - 0, 41, 33, 0, 0, 0, 55, 53, 0, 59, - 0, 45, 46, 0, 47, 0, 61, 48, 0, 0, - 0, 0, 38, 39, 40, 36, 0, 54, 57, 0, - 43, 0, 70, 71, 72, 73, 74, 75, 0, 0, - 0, 60, 59, 0, 33, 0, 0, 0, 56, 58, - 50, 0, 0, 0, 65, 63, 66, 64, 61, 0, - 0, 34, 32, 37, 0, 0, 43, 0, 0, 0, - 62, 49, 76, 35, 30, 44, 42, 0, 67, 68, - 0, 69 + 0, 51, 0, 29, 28, 0, 58, 0, 0, 0, + 0, 27, 31, 53, 53, 56, 0, 0, 0, 0, + 0, 0, 33, 0, 0, 54, 52, 0, 58, 0, + 44, 45, 0, 46, 0, 60, 47, 0, 0, 38, + 39, 40, 36, 0, 0, 0, 53, 56, 0, 42, + 0, 69, 70, 71, 72, 73, 74, 0, 0, 0, + 59, 58, 0, 0, 33, 0, 0, 55, 57, 49, + 0, 0, 0, 64, 62, 65, 63, 60, 0, 0, + 37, 0, 34, 32, 0, 42, 0, 0, 0, 61, + 48, 75, 35, 30, 43, 41, 0, 66, 67, 0, + 68 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int8 yypgoto[] = { - -95, -95, -95, -95, -95, -95, -95, -95, -95, -95, - -95, -95, -95, -95, -95, 17, 45, -95, -95, -95, - -95, -3, -90, -95, -95, -95, -95, -71, 36, -85, - 9, 28, -94, -95 + -94, -94, -94, -94, -94, -94, -94, -94, -94, -94, + -94, -94, -94, -94, -94, 17, 41, -94, -94, -94, + -2, -89, -94, -94, -94, -94, -71, 43, -84, 9, + 28, -93, -94 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { -1, 1, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 101, 82, 144, 105, 83, - 31, 132, 95, 32, 33, 34, 42, 61, 89, 78, - 121, 96, 118, 35 + 26, 27, 28, 29, 30, 104, 82, 141, 102, 31, + 131, 94, 32, 33, 34, 42, 61, 88, 78, 120, + 95, 117, 35 }; /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If @@ -748,40 +747,42 @@ static const yytype_int16 yydefgoto[] = number is the opposite. If YYTABLE_NINF, syntax error. */ static const yytype_uint8 yytable[] = { - 110, 119, 86, 87, 109, 2, 43, 44, 122, 3, + 109, 118, 85, 86, 108, 2, 43, 44, 121, 3, 4, 45, 59, 59, 5, 6, 7, 8, 9, 10, - 11, 60, 85, 47, 12, 13, 14, 46, 135, 137, - 15, 16, 48, 111, 91, 92, 128, 139, 94, 148, - 17, 146, 49, 50, 112, 113, 114, 115, 116, 117, - 112, 113, 114, 115, 116, 117, 51, 52, 158, 91, - 92, 93, 54, 94, 91, 92, 134, 53, 94, 91, - 92, 136, 63, 94, 91, 92, 157, 40, 94, 55, - 41, 102, 103, 104, 36, 38, 37, 39, 56, 57, - 58, 62, 64, 65, 66, 67, 69, 68, 71, 70, - 72, 73, 74, 75, 76, 77, 80, 90, 59, 79, - 88, 97, 81, 84, 98, 99, 100, 106, 107, 108, - 120, 123, 125, 126, 130, 142, 143, 127, 131, 133, - 140, 145, 151, 147, 152, 153, 149, 154, 156, 159, - 160, 141, 161, 155, 129, 124, 0, 150, 138 + 11, 60, 84, 47, 12, 13, 14, 46, 134, 136, + 15, 16, 36, 110, 37, 127, 48, 138, 54, 147, + 17, 145, 49, 50, 111, 112, 113, 114, 115, 116, + 111, 112, 113, 114, 115, 116, 51, 52, 157, 90, + 91, 92, 53, 93, 90, 91, 133, 55, 93, 90, + 91, 135, 62, 93, 90, 91, 156, 56, 93, 90, + 91, 63, 40, 93, 57, 41, 99, 100, 101, 38, + 58, 39, 64, 65, 66, 67, 69, 68, 71, 70, + 72, 73, 74, 75, 76, 77, 80, 79, 59, 81, + 87, 96, 83, 98, 89, 97, 105, 103, 106, 107, + 119, 122, 123, 129, 125, 126, 143, 130, 132, 144, + 139, 140, 148, 146, 150, 151, 152, 153, 155, 158, + 159, 142, 160, 154, 124, 0, 149, 137, 0, 0, + 128 }; static const yytype_int16 yycheck[] = { - 90, 95, 73, 74, 89, 0, 46, 7, 98, 4, + 89, 94, 73, 74, 88, 0, 46, 7, 97, 4, 5, 3, 18, 18, 9, 10, 11, 12, 13, 14, - 15, 27, 27, 30, 19, 20, 21, 28, 118, 119, - 25, 26, 46, 27, 44, 45, 107, 122, 48, 133, - 35, 131, 3, 3, 38, 39, 40, 41, 42, 43, - 38, 39, 40, 41, 42, 43, 3, 3, 148, 44, - 45, 46, 36, 48, 44, 45, 46, 3, 48, 44, - 45, 46, 3, 48, 44, 45, 46, 46, 48, 46, - 49, 22, 23, 24, 6, 6, 8, 8, 46, 46, - 46, 30, 3, 46, 46, 33, 16, 37, 3, 34, - 3, 46, 46, 46, 29, 31, 48, 16, 18, 46, - 18, 3, 46, 46, 38, 28, 18, 16, 46, 46, - 32, 6, 17, 16, 3, 3, 44, 46, 18, 46, - 46, 17, 3, 17, 3, 17, 27, 3, 3, 46, - 27, 124, 46, 146, 108, 100, -1, 138, 120 + 15, 27, 27, 30, 19, 20, 21, 28, 117, 118, + 25, 26, 6, 27, 8, 106, 46, 121, 36, 132, + 35, 130, 3, 3, 38, 39, 40, 41, 42, 43, + 38, 39, 40, 41, 42, 43, 3, 3, 147, 44, + 45, 46, 3, 48, 44, 45, 46, 46, 48, 44, + 45, 46, 30, 48, 44, 45, 46, 46, 48, 44, + 45, 3, 46, 48, 46, 49, 22, 23, 24, 6, + 46, 8, 3, 46, 46, 33, 16, 37, 3, 34, + 3, 46, 46, 46, 29, 31, 48, 46, 18, 46, + 18, 3, 46, 28, 16, 38, 16, 18, 46, 46, + 32, 6, 16, 3, 17, 46, 3, 18, 46, 17, + 46, 44, 27, 17, 3, 3, 17, 3, 3, 46, + 27, 124, 46, 145, 103, -1, 137, 119, -1, -1, + 107 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing @@ -791,20 +792,20 @@ static const yytype_int8 yystos[] = 0, 52, 0, 4, 5, 9, 10, 11, 12, 13, 14, 15, 19, 20, 21, 25, 26, 35, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, - 65, 71, 74, 75, 76, 84, 6, 8, 6, 8, - 46, 49, 77, 46, 7, 3, 28, 30, 46, 3, + 65, 70, 73, 74, 75, 83, 6, 8, 6, 8, + 46, 49, 76, 46, 7, 3, 28, 30, 46, 3, 3, 3, 3, 3, 36, 46, 46, 46, 46, 18, - 27, 78, 30, 3, 3, 46, 46, 33, 37, 16, - 34, 3, 3, 46, 46, 46, 29, 31, 80, 46, - 48, 46, 67, 70, 46, 27, 78, 78, 18, 79, - 16, 44, 45, 46, 48, 73, 82, 3, 38, 28, - 18, 66, 22, 23, 24, 69, 16, 46, 46, 80, - 73, 27, 38, 39, 40, 41, 42, 43, 83, 83, - 32, 81, 73, 6, 67, 17, 16, 46, 78, 79, - 3, 18, 72, 46, 46, 73, 46, 73, 82, 80, - 46, 66, 3, 44, 68, 17, 73, 17, 83, 27, - 81, 3, 3, 17, 3, 72, 3, 46, 73, 46, - 27, 46 + 27, 77, 30, 3, 3, 46, 46, 33, 37, 16, + 34, 3, 3, 46, 46, 46, 29, 31, 79, 46, + 48, 46, 67, 46, 27, 77, 77, 18, 78, 16, + 44, 45, 46, 48, 72, 81, 3, 38, 28, 22, + 23, 24, 69, 18, 66, 16, 46, 46, 79, 72, + 27, 38, 39, 40, 41, 42, 43, 82, 82, 32, + 80, 72, 6, 16, 67, 17, 46, 77, 78, 3, + 18, 71, 46, 46, 72, 46, 72, 81, 79, 46, + 44, 68, 66, 3, 17, 72, 17, 82, 27, 80, + 3, 3, 17, 3, 71, 3, 46, 72, 46, 27, + 46 }; /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ @@ -814,10 +815,10 @@ static const yytype_int8 yyr1[] = 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 66, 67, 67, 68, 69, 69, - 69, 70, 71, 72, 72, 73, 73, 73, 74, 75, - 76, 77, 77, 77, 78, 78, 78, 79, 79, 80, - 80, 81, 81, 82, 82, 82, 82, 82, 82, 82, - 83, 83, 83, 83, 83, 83, 84 + 69, 70, 71, 71, 72, 72, 72, 73, 74, 75, + 76, 76, 76, 77, 77, 77, 78, 78, 79, 79, + 80, 80, 81, 81, 81, 81, 81, 81, 81, 82, + 82, 82, 82, 82, 82, 83 }; /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ @@ -827,10 +828,10 @@ static const yytype_int8 yyr2[] = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 4, 3, 3, 9, 4, 8, 0, 3, 5, 2, 1, 1, 1, - 1, 1, 9, 0, 3, 1, 1, 1, 5, 8, - 7, 1, 2, 4, 0, 3, 5, 0, 3, 0, - 3, 0, 3, 3, 3, 3, 3, 5, 5, 7, - 1, 1, 1, 1, 1, 1, 8 + 1, 9, 0, 3, 1, 1, 1, 5, 8, 7, + 1, 2, 4, 0, 3, 5, 0, 3, 0, 3, + 0, 3, 3, 3, 3, 3, 5, 5, 7, 1, + 1, 1, 1, 1, 1, 8 }; @@ -1310,7 +1311,7 @@ yyreduce: { CONTEXT->ssql->flag=SCF_EXIT;//"exit"; } -#line 1314 "yacc_sql.cpp" +#line 1315 "yacc_sql.cpp" break; case 22: /* help: HELP SEMICOLON */ @@ -1318,7 +1319,7 @@ yyreduce: { CONTEXT->ssql->flag=SCF_HELP;//"help"; } -#line 1322 "yacc_sql.cpp" +#line 1323 "yacc_sql.cpp" break; case 23: /* sync: SYNC SEMICOLON */ @@ -1326,7 +1327,7 @@ yyreduce: { CONTEXT->ssql->flag = SCF_SYNC; } -#line 1330 "yacc_sql.cpp" +#line 1331 "yacc_sql.cpp" break; case 24: /* begin: TRX_BEGIN SEMICOLON */ @@ -1334,7 +1335,7 @@ yyreduce: { CONTEXT->ssql->flag = SCF_BEGIN; } -#line 1338 "yacc_sql.cpp" +#line 1339 "yacc_sql.cpp" break; case 25: /* commit: TRX_COMMIT SEMICOLON */ @@ -1342,7 +1343,7 @@ yyreduce: { CONTEXT->ssql->flag = SCF_COMMIT; } -#line 1346 "yacc_sql.cpp" +#line 1347 "yacc_sql.cpp" break; case 26: /* rollback: TRX_ROLLBACK SEMICOLON */ @@ -1350,7 +1351,7 @@ yyreduce: { CONTEXT->ssql->flag = SCF_ROLLBACK; } -#line 1354 "yacc_sql.cpp" +#line 1355 "yacc_sql.cpp" break; case 27: /* drop_table: DROP TABLE ID SEMICOLON */ @@ -1359,7 +1360,7 @@ yyreduce: CONTEXT->ssql->flag = SCF_DROP_TABLE;//"drop_table"; drop_table_init(&CONTEXT->ssql->sstr.drop_table, (yyvsp[-1].string)); } -#line 1363 "yacc_sql.cpp" +#line 1364 "yacc_sql.cpp" break; case 28: /* show_tables: SHOW TABLES SEMICOLON */ @@ -1367,7 +1368,7 @@ yyreduce: { CONTEXT->ssql->flag = SCF_SHOW_TABLES; } -#line 1371 "yacc_sql.cpp" +#line 1372 "yacc_sql.cpp" break; case 29: /* desc_table: DESC ID SEMICOLON */ @@ -1376,408 +1377,400 @@ yyreduce: CONTEXT->ssql->flag = SCF_DESC_TABLE; desc_table_init(&CONTEXT->ssql->sstr.desc_table, (yyvsp[-1].string)); } -#line 1380 "yacc_sql.cpp" +#line 1381 "yacc_sql.cpp" break; case 30: /* create_index: CREATE INDEX ID ON ID LBRACE ID RBRACE SEMICOLON */ #line 212 "yacc_sql.y" - { - CONTEXT->ssql->flag = SCF_CREATE_INDEX;//"create_index"; - create_index_init(&CONTEXT->ssql->sstr.create_index, (yyvsp[-6].string), (yyvsp[-4].string), (yyvsp[-2].string)); - } -#line 1389 "yacc_sql.cpp" + { + CONTEXT->ssql->flag = SCF_CREATE_INDEX;//"create_index"; + create_index_init(&CONTEXT->ssql->sstr.create_index, (yyvsp[-6].string), (yyvsp[-4].string), (yyvsp[-2].string)); + } +#line 1390 "yacc_sql.cpp" break; case 31: /* drop_index: DROP INDEX ID SEMICOLON */ #line 220 "yacc_sql.y" - { - CONTEXT->ssql->flag=SCF_DROP_INDEX;//"drop_index"; - drop_index_init(&CONTEXT->ssql->sstr.drop_index, (yyvsp[-1].string)); - } -#line 1398 "yacc_sql.cpp" + { + CONTEXT->ssql->flag=SCF_DROP_INDEX;//"drop_index"; + drop_index_init(&CONTEXT->ssql->sstr.drop_index, (yyvsp[-1].string)); + } +#line 1399 "yacc_sql.cpp" break; case 32: /* create_table: CREATE TABLE ID LBRACE attr_def attr_def_list RBRACE SEMICOLON */ #line 227 "yacc_sql.y" - { - CONTEXT->ssql->flag=SCF_CREATE_TABLE;//"create_table"; - create_table_init_name(&CONTEXT->ssql->sstr.create_table, (yyvsp[-5].string)); - //临时变量清零 - CONTEXT->value_length = 0; - } -#line 1409 "yacc_sql.cpp" + { + CONTEXT->ssql->flag=SCF_CREATE_TABLE;//"create_table"; + create_table_init_name(&CONTEXT->ssql->sstr.create_table, (yyvsp[-5].string)); + //临时变量清零 + CONTEXT->value_length = 0; + } +#line 1410 "yacc_sql.cpp" break; case 34: /* attr_def_list: COMMA attr_def attr_def_list */ #line 236 "yacc_sql.y" { } -#line 1415 "yacc_sql.cpp" +#line 1416 "yacc_sql.cpp" break; - case 35: /* attr_def: ID_get type LBRACE number RBRACE */ + case 35: /* attr_def: ID type LBRACE number RBRACE */ #line 241 "yacc_sql.y" - { - AttrInfo attribute; - attr_info_init(&attribute, CONTEXT->id, (AttrType)(yyvsp[-3].number), (yyvsp[-1].number)); - create_table_append_attribute(&CONTEXT->ssql->sstr.create_table, &attribute); - CONTEXT->value_length++; - } -#line 1426 "yacc_sql.cpp" + { + AttrInfo attribute; + attr_info_init(&attribute, (yyvsp[-4].string), (AttrType)(yyvsp[-3].number), (yyvsp[-1].number)); + create_table_append_attribute(&CONTEXT->ssql->sstr.create_table, &attribute); + CONTEXT->value_length++; + } +#line 1427 "yacc_sql.cpp" break; - case 36: /* attr_def: ID_get type */ + case 36: /* attr_def: ID type */ #line 248 "yacc_sql.y" - { - AttrInfo attribute; - attr_info_init(&attribute, CONTEXT->id, (AttrType)(yyvsp[0].number), 4); - create_table_append_attribute(&CONTEXT->ssql->sstr.create_table, &attribute); - CONTEXT->value_length++; - } -#line 1437 "yacc_sql.cpp" + { + AttrInfo attribute; + attr_info_init(&attribute, (yyvsp[-1].string), (AttrType)(yyvsp[0].number), 4); + create_table_append_attribute(&CONTEXT->ssql->sstr.create_table, &attribute); + CONTEXT->value_length++; + } +#line 1438 "yacc_sql.cpp" break; case 37: /* number: NUMBER */ #line 256 "yacc_sql.y" - {(yyval.number) = (yyvsp[0].number);} -#line 1443 "yacc_sql.cpp" + {(yyval.number) = (yyvsp[0].number);} +#line 1444 "yacc_sql.cpp" break; case 38: /* type: INT_T */ #line 259 "yacc_sql.y" - { (yyval.number)=INTS; } -#line 1449 "yacc_sql.cpp" + { (yyval.number)=INTS; } +#line 1450 "yacc_sql.cpp" break; case 39: /* type: STRING_T */ #line 260 "yacc_sql.y" { (yyval.number)=CHARS; } -#line 1455 "yacc_sql.cpp" +#line 1456 "yacc_sql.cpp" break; case 40: /* type: FLOAT_T */ #line 261 "yacc_sql.y" { (yyval.number)=FLOATS; } -#line 1461 "yacc_sql.cpp" +#line 1462 "yacc_sql.cpp" break; - case 41: /* ID_get: ID */ + case 41: /* insert: INSERT INTO ID VALUES LBRACE value value_list RBRACE SEMICOLON */ #line 265 "yacc_sql.y" - { - char *temp=(yyvsp[0].string); - snprintf(CONTEXT->id, sizeof(CONTEXT->id), "%s", temp); - } -#line 1470 "yacc_sql.cpp" - break; - - case 42: /* insert: INSERT INTO ID VALUES LBRACE value value_list RBRACE SEMICOLON */ -#line 274 "yacc_sql.y" - { - CONTEXT->ssql->flag=SCF_INSERT;//"insert"; - inserts_init(&CONTEXT->ssql->sstr.insertion, (yyvsp[-6].string), CONTEXT->values, CONTEXT->value_length); + { + CONTEXT->ssql->flag=SCF_INSERT;//"insert"; + inserts_init(&CONTEXT->ssql->sstr.insertion, (yyvsp[-6].string), CONTEXT->values, CONTEXT->value_length); //临时变量清零 CONTEXT->value_length=0; } -#line 1482 "yacc_sql.cpp" +#line 1474 "yacc_sql.cpp" break; - case 44: /* value_list: COMMA value value_list */ -#line 284 "yacc_sql.y" + case 43: /* value_list: COMMA value value_list */ +#line 275 "yacc_sql.y" { - // CONTEXT->values[CONTEXT->value_length++] = *$2; - } -#line 1490 "yacc_sql.cpp" + // CONTEXT->values[CONTEXT->value_length++] = *$2; + } +#line 1482 "yacc_sql.cpp" break; - case 45: /* value: NUMBER */ -#line 289 "yacc_sql.y" - { - value_init_integer(&CONTEXT->values[CONTEXT->value_length++], (yyvsp[0].number)); - } -#line 1498 "yacc_sql.cpp" + case 44: /* value: NUMBER */ +#line 280 "yacc_sql.y" + { + value_init_integer(&CONTEXT->values[CONTEXT->value_length++], (yyvsp[0].number)); + } +#line 1490 "yacc_sql.cpp" break; - case 46: /* value: FLOAT */ -#line 292 "yacc_sql.y" + case 45: /* value: FLOAT */ +#line 283 "yacc_sql.y" { - value_init_float(&CONTEXT->values[CONTEXT->value_length++], (yyvsp[0].floats)); - } -#line 1506 "yacc_sql.cpp" + value_init_float(&CONTEXT->values[CONTEXT->value_length++], (yyvsp[0].floats)); + } +#line 1498 "yacc_sql.cpp" break; - case 47: /* value: SSS */ -#line 295 "yacc_sql.y" + case 46: /* value: SSS */ +#line 286 "yacc_sql.y" { - (yyvsp[0].string) = substr((yyvsp[0].string),1,strlen((yyvsp[0].string))-2); - value_init_string(&CONTEXT->values[CONTEXT->value_length++], (yyvsp[0].string)); - } -#line 1515 "yacc_sql.cpp" + char *tmp = substr((yyvsp[0].string),1,strlen((yyvsp[0].string))-2); + value_init_string(&CONTEXT->values[CONTEXT->value_length++], tmp); + free((yyvsp[0].string)); + } +#line 1508 "yacc_sql.cpp" break; - case 48: /* delete: DELETE FROM ID where SEMICOLON */ -#line 303 "yacc_sql.y" - { - CONTEXT->ssql->flag = SCF_DELETE;//"delete"; - deletes_init_relation(&CONTEXT->ssql->sstr.deletion, (yyvsp[-2].string)); - deletes_set_conditions(&CONTEXT->ssql->sstr.deletion, - CONTEXT->conditions, CONTEXT->condition_length); - CONTEXT->condition_length = 0; + case 47: /* delete: DELETE FROM ID where SEMICOLON */ +#line 295 "yacc_sql.y" + { + CONTEXT->ssql->flag = SCF_DELETE;//"delete"; + deletes_init_relation(&CONTEXT->ssql->sstr.deletion, (yyvsp[-2].string)); + deletes_set_conditions(&CONTEXT->ssql->sstr.deletion, + CONTEXT->conditions, CONTEXT->condition_length); + CONTEXT->condition_length = 0; } -#line 1527 "yacc_sql.cpp" +#line 1520 "yacc_sql.cpp" break; - case 49: /* update: UPDATE ID SET ID EQ value where SEMICOLON */ -#line 313 "yacc_sql.y" - { - CONTEXT->ssql->flag = SCF_UPDATE;//"update"; - Value *value = &CONTEXT->values[0]; - updates_init(&CONTEXT->ssql->sstr.update, (yyvsp[-6].string), (yyvsp[-4].string), value, - CONTEXT->conditions, CONTEXT->condition_length); - CONTEXT->condition_length = 0; - } -#line 1539 "yacc_sql.cpp" + case 48: /* update: UPDATE ID SET ID EQ value where SEMICOLON */ +#line 305 "yacc_sql.y" + { + CONTEXT->ssql->flag = SCF_UPDATE;//"update"; + Value *value = &CONTEXT->values[0]; + updates_init(&CONTEXT->ssql->sstr.update, (yyvsp[-6].string), (yyvsp[-4].string), value, + CONTEXT->conditions, CONTEXT->condition_length); + CONTEXT->condition_length = 0; + } +#line 1532 "yacc_sql.cpp" break; - case 50: /* select: SELECT select_attr FROM ID rel_list where SEMICOLON */ -#line 323 "yacc_sql.y" - { - selects_append_relation(&CONTEXT->ssql->sstr.selection, (yyvsp[-3].string)); + case 49: /* select: SELECT select_attr FROM ID rel_list where SEMICOLON */ +#line 315 "yacc_sql.y" + { + selects_append_relation(&CONTEXT->ssql->sstr.selection, (yyvsp[-3].string)); - selects_append_conditions(&CONTEXT->ssql->sstr.selection, CONTEXT->conditions, CONTEXT->condition_length); + selects_append_conditions(&CONTEXT->ssql->sstr.selection, CONTEXT->conditions, CONTEXT->condition_length); - CONTEXT->ssql->flag=SCF_SELECT;//"select"; + CONTEXT->ssql->flag=SCF_SELECT;//"select"; - //临时变量清零 - CONTEXT->condition_length=0; - CONTEXT->from_length=0; - CONTEXT->select_length=0; - CONTEXT->value_length = 0; - } -#line 1557 "yacc_sql.cpp" + //临时变量清零 + CONTEXT->condition_length=0; + CONTEXT->from_length=0; + CONTEXT->select_length=0; + CONTEXT->value_length = 0; + } +#line 1550 "yacc_sql.cpp" break; - case 51: /* select_attr: STAR */ -#line 339 "yacc_sql.y" + case 50: /* select_attr: STAR */ +#line 331 "yacc_sql.y" { - RelAttr attr; - relation_attr_init(&attr, NULL, "*"); - selects_append_attribute(&CONTEXT->ssql->sstr.selection, &attr); - } -#line 1567 "yacc_sql.cpp" + RelAttr attr; + relation_attr_init(&attr, NULL, strdup("*")); + selects_append_attribute(&CONTEXT->ssql->sstr.selection, &attr); + } +#line 1560 "yacc_sql.cpp" break; - case 52: /* select_attr: ID attr_list */ -#line 344 "yacc_sql.y" + case 51: /* select_attr: ID attr_list */ +#line 336 "yacc_sql.y" { - RelAttr attr; - relation_attr_init(&attr, NULL, (yyvsp[-1].string)); - selects_append_attribute(&CONTEXT->ssql->sstr.selection, &attr); - } -#line 1577 "yacc_sql.cpp" + RelAttr attr; + relation_attr_init(&attr, NULL, (yyvsp[-1].string)); + selects_append_attribute(&CONTEXT->ssql->sstr.selection, &attr); + } +#line 1570 "yacc_sql.cpp" break; - case 53: /* select_attr: ID DOT ID attr_list */ -#line 349 "yacc_sql.y" - { - RelAttr attr; - relation_attr_init(&attr, (yyvsp[-3].string), (yyvsp[-1].string)); - selects_append_attribute(&CONTEXT->ssql->sstr.selection, &attr); - } -#line 1587 "yacc_sql.cpp" + case 52: /* select_attr: ID DOT ID attr_list */ +#line 341 "yacc_sql.y" + { + RelAttr attr; + relation_attr_init(&attr, (yyvsp[-3].string), (yyvsp[-1].string)); + selects_append_attribute(&CONTEXT->ssql->sstr.selection, &attr); + } +#line 1580 "yacc_sql.cpp" break; - case 55: /* attr_list: COMMA ID attr_list */ -#line 357 "yacc_sql.y" + case 54: /* attr_list: COMMA ID attr_list */ +#line 349 "yacc_sql.y" { - RelAttr attr; - relation_attr_init(&attr, NULL, (yyvsp[-1].string)); - selects_append_attribute(&CONTEXT->ssql->sstr.selection, &attr); + RelAttr attr; + relation_attr_init(&attr, NULL, (yyvsp[-1].string)); + selects_append_attribute(&CONTEXT->ssql->sstr.selection, &attr); } -#line 1597 "yacc_sql.cpp" +#line 1590 "yacc_sql.cpp" break; - case 56: /* attr_list: COMMA ID DOT ID attr_list */ -#line 362 "yacc_sql.y" + case 55: /* attr_list: COMMA ID DOT ID attr_list */ +#line 354 "yacc_sql.y" { - RelAttr attr; - relation_attr_init(&attr, (yyvsp[-3].string), (yyvsp[-1].string)); - selects_append_attribute(&CONTEXT->ssql->sstr.selection, &attr); - } -#line 1607 "yacc_sql.cpp" + RelAttr attr; + relation_attr_init(&attr, (yyvsp[-3].string), (yyvsp[-1].string)); + selects_append_attribute(&CONTEXT->ssql->sstr.selection, &attr); + } +#line 1600 "yacc_sql.cpp" break; - case 58: /* rel_list: COMMA ID rel_list */ -#line 371 "yacc_sql.y" - { - selects_append_relation(&CONTEXT->ssql->sstr.selection, (yyvsp[-1].string)); - } -#line 1615 "yacc_sql.cpp" + case 57: /* rel_list: COMMA ID rel_list */ +#line 363 "yacc_sql.y" + { + selects_append_relation(&CONTEXT->ssql->sstr.selection, (yyvsp[-1].string)); + } +#line 1608 "yacc_sql.cpp" break; - case 60: /* where: WHERE condition condition_list */ -#line 377 "yacc_sql.y" - { - // CONTEXT->conditions[CONTEXT->condition_length++]=*$2; - } -#line 1623 "yacc_sql.cpp" + case 59: /* where: WHERE condition condition_list */ +#line 369 "yacc_sql.y" + { + // CONTEXT->conditions[CONTEXT->condition_length++]=*$2; + } +#line 1616 "yacc_sql.cpp" break; - case 62: /* condition_list: AND condition condition_list */ -#line 383 "yacc_sql.y" + case 61: /* condition_list: AND condition condition_list */ +#line 375 "yacc_sql.y" { - // CONTEXT->conditions[CONTEXT->condition_length++]=*$2; - } -#line 1631 "yacc_sql.cpp" + // CONTEXT->conditions[CONTEXT->condition_length++]=*$2; + } +#line 1624 "yacc_sql.cpp" break; - case 63: /* condition: ID comOp value */ -#line 389 "yacc_sql.y" - { - RelAttr left_attr; - relation_attr_init(&left_attr, NULL, (yyvsp[-2].string)); + case 62: /* condition: ID comOp value */ +#line 381 "yacc_sql.y" + { + RelAttr left_attr; + relation_attr_init(&left_attr, NULL, (yyvsp[-2].string)); - Value *right_value = &CONTEXT->values[CONTEXT->value_length - 1]; + Value *right_value = &CONTEXT->values[CONTEXT->value_length - 1]; - Condition condition; - condition_init(&condition, CONTEXT->comp, 1, &left_attr, NULL, 0, NULL, right_value); - CONTEXT->conditions[CONTEXT->condition_length++] = condition; - } -#line 1646 "yacc_sql.cpp" + Condition condition; + condition_init(&condition, CONTEXT->comp, 1, &left_attr, NULL, 0, NULL, right_value); + CONTEXT->conditions[CONTEXT->condition_length++] = condition; + } +#line 1639 "yacc_sql.cpp" break; - case 64: /* condition: value comOp value */ -#line 400 "yacc_sql.y" - { - Value *left_value = &CONTEXT->values[CONTEXT->value_length - 2]; - Value *right_value = &CONTEXT->values[CONTEXT->value_length - 1]; - - Condition condition; - condition_init(&condition, CONTEXT->comp, 0, NULL, left_value, 0, NULL, right_value); - CONTEXT->conditions[CONTEXT->condition_length++] = condition; - } -#line 1659 "yacc_sql.cpp" + case 63: /* condition: value comOp value */ +#line 392 "yacc_sql.y" + { + Value *left_value = &CONTEXT->values[CONTEXT->value_length - 2]; + Value *right_value = &CONTEXT->values[CONTEXT->value_length - 1]; + + Condition condition; + condition_init(&condition, CONTEXT->comp, 0, NULL, left_value, 0, NULL, right_value); + CONTEXT->conditions[CONTEXT->condition_length++] = condition; + } +#line 1652 "yacc_sql.cpp" break; - case 65: /* condition: ID comOp ID */ -#line 409 "yacc_sql.y" - { - RelAttr left_attr; - relation_attr_init(&left_attr, NULL, (yyvsp[-2].string)); - RelAttr right_attr; - relation_attr_init(&right_attr, NULL, (yyvsp[0].string)); - - Condition condition; - condition_init(&condition, CONTEXT->comp, 1, &left_attr, NULL, 1, &right_attr, NULL); - CONTEXT->conditions[CONTEXT->condition_length++] = condition; - } -#line 1674 "yacc_sql.cpp" + case 64: /* condition: ID comOp ID */ +#line 401 "yacc_sql.y" + { + RelAttr left_attr; + relation_attr_init(&left_attr, NULL, (yyvsp[-2].string)); + RelAttr right_attr; + relation_attr_init(&right_attr, NULL, (yyvsp[0].string)); + + Condition condition; + condition_init(&condition, CONTEXT->comp, 1, &left_attr, NULL, 1, &right_attr, NULL); + CONTEXT->conditions[CONTEXT->condition_length++] = condition; + } +#line 1667 "yacc_sql.cpp" break; - case 66: /* condition: value comOp ID */ -#line 420 "yacc_sql.y" - { - Value *left_value = &CONTEXT->values[CONTEXT->value_length - 1]; - RelAttr right_attr; - relation_attr_init(&right_attr, NULL, (yyvsp[0].string)); - - Condition condition; - condition_init(&condition, CONTEXT->comp, 0, NULL, left_value, 1, &right_attr, NULL); - CONTEXT->conditions[CONTEXT->condition_length++] = condition; - } -#line 1688 "yacc_sql.cpp" + case 65: /* condition: value comOp ID */ +#line 412 "yacc_sql.y" + { + Value *left_value = &CONTEXT->values[CONTEXT->value_length - 1]; + RelAttr right_attr; + relation_attr_init(&right_attr, NULL, (yyvsp[0].string)); + + Condition condition; + condition_init(&condition, CONTEXT->comp, 0, NULL, left_value, 1, &right_attr, NULL); + CONTEXT->conditions[CONTEXT->condition_length++] = condition; + } +#line 1681 "yacc_sql.cpp" break; - case 67: /* condition: ID DOT ID comOp value */ -#line 430 "yacc_sql.y" - { - RelAttr left_attr; - relation_attr_init(&left_attr, (yyvsp[-4].string), (yyvsp[-2].string)); - Value *right_value = &CONTEXT->values[CONTEXT->value_length - 1]; + case 66: /* condition: ID DOT ID comOp value */ +#line 422 "yacc_sql.y" + { + RelAttr left_attr; + relation_attr_init(&left_attr, (yyvsp[-4].string), (yyvsp[-2].string)); + Value *right_value = &CONTEXT->values[CONTEXT->value_length - 1]; - Condition condition; - condition_init(&condition, CONTEXT->comp, 1, &left_attr, NULL, 0, NULL, right_value); - CONTEXT->conditions[CONTEXT->condition_length++] = condition; + Condition condition; + condition_init(&condition, CONTEXT->comp, 1, &left_attr, NULL, 0, NULL, right_value); + CONTEXT->conditions[CONTEXT->condition_length++] = condition; } -#line 1702 "yacc_sql.cpp" +#line 1695 "yacc_sql.cpp" break; - case 68: /* condition: value comOp ID DOT ID */ -#line 440 "yacc_sql.y" - { - Value *left_value = &CONTEXT->values[CONTEXT->value_length - 1]; + case 67: /* condition: value comOp ID DOT ID */ +#line 432 "yacc_sql.y" + { + Value *left_value = &CONTEXT->values[CONTEXT->value_length - 1]; - RelAttr right_attr; - relation_attr_init(&right_attr, (yyvsp[-2].string), (yyvsp[0].string)); + RelAttr right_attr; + relation_attr_init(&right_attr, (yyvsp[-2].string), (yyvsp[0].string)); - Condition condition; - condition_init(&condition, CONTEXT->comp, 0, NULL, left_value, 1, &right_attr, NULL); - CONTEXT->conditions[CONTEXT->condition_length++] = condition; + Condition condition; + condition_init(&condition, CONTEXT->comp, 0, NULL, left_value, 1, &right_attr, NULL); + CONTEXT->conditions[CONTEXT->condition_length++] = condition; } -#line 1717 "yacc_sql.cpp" +#line 1710 "yacc_sql.cpp" break; - case 69: /* condition: ID DOT ID comOp ID DOT ID */ -#line 451 "yacc_sql.y" - { - RelAttr left_attr; - relation_attr_init(&left_attr, (yyvsp[-6].string), (yyvsp[-4].string)); - RelAttr right_attr; - relation_attr_init(&right_attr, (yyvsp[-2].string), (yyvsp[0].string)); - - Condition condition; - condition_init(&condition, CONTEXT->comp, 1, &left_attr, NULL, 1, &right_attr, NULL); - CONTEXT->conditions[CONTEXT->condition_length++] = condition; + case 68: /* condition: ID DOT ID comOp ID DOT ID */ +#line 443 "yacc_sql.y" + { + RelAttr left_attr; + relation_attr_init(&left_attr, (yyvsp[-6].string), (yyvsp[-4].string)); + RelAttr right_attr; + relation_attr_init(&right_attr, (yyvsp[-2].string), (yyvsp[0].string)); + + Condition condition; + condition_init(&condition, CONTEXT->comp, 1, &left_attr, NULL, 1, &right_attr, NULL); + CONTEXT->conditions[CONTEXT->condition_length++] = condition; } -#line 1732 "yacc_sql.cpp" +#line 1725 "yacc_sql.cpp" break; - case 70: /* comOp: EQ */ -#line 464 "yacc_sql.y" - { CONTEXT->comp = EQUAL_TO; } -#line 1738 "yacc_sql.cpp" + case 69: /* comOp: EQ */ +#line 456 "yacc_sql.y" + { CONTEXT->comp = EQUAL_TO; } +#line 1731 "yacc_sql.cpp" break; - case 71: /* comOp: LT */ -#line 465 "yacc_sql.y" + case 70: /* comOp: LT */ +#line 457 "yacc_sql.y" { CONTEXT->comp = LESS_THAN; } -#line 1744 "yacc_sql.cpp" +#line 1737 "yacc_sql.cpp" break; - case 72: /* comOp: GT */ -#line 466 "yacc_sql.y" + case 71: /* comOp: GT */ +#line 458 "yacc_sql.y" { CONTEXT->comp = GREAT_THAN; } -#line 1750 "yacc_sql.cpp" +#line 1743 "yacc_sql.cpp" break; - case 73: /* comOp: LE */ -#line 467 "yacc_sql.y" + case 72: /* comOp: LE */ +#line 459 "yacc_sql.y" { CONTEXT->comp = LESS_EQUAL; } -#line 1756 "yacc_sql.cpp" +#line 1749 "yacc_sql.cpp" break; - case 74: /* comOp: GE */ -#line 468 "yacc_sql.y" + case 73: /* comOp: GE */ +#line 460 "yacc_sql.y" { CONTEXT->comp = GREAT_EQUAL; } -#line 1762 "yacc_sql.cpp" +#line 1755 "yacc_sql.cpp" break; - case 75: /* comOp: NE */ -#line 469 "yacc_sql.y" + case 74: /* comOp: NE */ +#line 461 "yacc_sql.y" { CONTEXT->comp = NOT_EQUAL; } -#line 1768 "yacc_sql.cpp" +#line 1761 "yacc_sql.cpp" break; - case 76: /* load_data: LOAD DATA INFILE SSS INTO TABLE ID SEMICOLON */ -#line 474 "yacc_sql.y" - { - CONTEXT->ssql->flag = SCF_LOAD_DATA; - load_data_init(&CONTEXT->ssql->sstr.load_data, (yyvsp[-1].string), (yyvsp[-4].string)); - } -#line 1777 "yacc_sql.cpp" + case 75: /* load_data: LOAD DATA INFILE SSS INTO TABLE ID SEMICOLON */ +#line 466 "yacc_sql.y" + { + CONTEXT->ssql->flag = SCF_LOAD_DATA; + load_data_init(&CONTEXT->ssql->sstr.load_data, (yyvsp[-1].string), (yyvsp[-4].string)); + } +#line 1770 "yacc_sql.cpp" break; -#line 1781 "yacc_sql.cpp" +#line 1774 "yacc_sql.cpp" default: break; } @@ -1971,20 +1964,20 @@ yyreturn: return yyresult; } -#line 479 "yacc_sql.y" +#line 471 "yacc_sql.y" //_____________________________________________________________________ extern void scan_string(const char *str, yyscan_t scanner); int sql_parse(const char *s, Query *sqls){ - ParserContext context; - memset(&context, 0, sizeof(context)); - - yyscan_t scanner; - yylex_init_extra(&context, &scanner); - context.ssql = sqls; - scan_string(s, scanner); - int result = yyparse(scanner); - yylex_destroy(scanner); - return result; + ParserContext context; + memset(&context, 0, sizeof(context)); + + yyscan_t scanner; + yylex_init_extra(&context, &scanner); + context.ssql = sqls; + scan_string(s, scanner); + int result = yyparse(scanner); + yylex_destroy(scanner); + return result; } diff --git a/src/observer/sql/parser/yacc_sql.hpp b/src/observer/sql/parser/yacc_sql.hpp index 6106ccc..8318240 100644 --- a/src/observer/sql/parser/yacc_sql.hpp +++ b/src/observer/sql/parser/yacc_sql.hpp @@ -118,7 +118,7 @@ union YYSTYPE char *string; int number; float floats; - char *position; + char *position; #line 124 "yacc_sql.hpp" diff --git a/src/observer/sql/parser/yacc_sql.y b/src/observer/sql/parser/yacc_sql.y index f80a89d..ae3a02a 100644 --- a/src/observer/sql/parser/yacc_sql.y +++ b/src/observer/sql/parser/yacc_sql.y @@ -19,7 +19,7 @@ typedef struct ParserContext { Value values[MAX_NUM]; Condition conditions[MAX_NUM]; CompOp comp; - char id[MAX_NUM]; + char id[MAX_NUM]; } ParserContext; //获取子串 @@ -110,7 +110,7 @@ ParserContext *get_context(yyscan_t scanner) char *string; int number; float floats; - char *position; + char *position; } %token NUMBER @@ -129,32 +129,32 @@ ParserContext *get_context(yyscan_t scanner) %% -commands: //commands or sqls. parser starts here. +commands: //commands or sqls. parser starts here. /* empty */ | commands command ; command: - select - | insert - | update - | delete - | create_table - | drop_table - | show_tables - | desc_table - | create_index - | drop_index - | sync - | begin - | commit - | rollback - | load_data - | help - | exit + select + | insert + | update + | delete + | create_table + | drop_table + | show_tables + | desc_table + | create_index + | drop_index + | sync + | begin + | commit + | rollback + | load_data + | help + | exit ; -exit: +exit: EXIT SEMICOLON { CONTEXT->ssql->flag=SCF_EXIT;//"exit"; }; @@ -188,7 +188,7 @@ rollback: } ; -drop_table: /*drop table 语句的语法解析树*/ +drop_table: /*drop table 语句的语法解析树*/ DROP TABLE ID SEMICOLON { CONTEXT->ssql->flag = SCF_DROP_TABLE;//"drop_table"; drop_table_init(&CONTEXT->ssql->sstr.drop_table, $3); @@ -207,29 +207,29 @@ desc_table: } ; -create_index: /*create index 语句的语法解析树*/ +create_index: /*create index 语句的语法解析树*/ CREATE INDEX ID ON ID LBRACE ID RBRACE SEMICOLON - { - CONTEXT->ssql->flag = SCF_CREATE_INDEX;//"create_index"; - create_index_init(&CONTEXT->ssql->sstr.create_index, $3, $5, $7); - } + { + CONTEXT->ssql->flag = SCF_CREATE_INDEX;//"create_index"; + create_index_init(&CONTEXT->ssql->sstr.create_index, $3, $5, $7); + } ; -drop_index: /*drop index 语句的语法解析树*/ +drop_index: /*drop index 语句的语法解析树*/ DROP INDEX ID SEMICOLON - { - CONTEXT->ssql->flag=SCF_DROP_INDEX;//"drop_index"; - drop_index_init(&CONTEXT->ssql->sstr.drop_index, $3); - } + { + CONTEXT->ssql->flag=SCF_DROP_INDEX;//"drop_index"; + drop_index_init(&CONTEXT->ssql->sstr.drop_index, $3); + } ; -create_table: /*create table 语句的语法解析树*/ +create_table: /*create table 语句的语法解析树*/ CREATE TABLE ID LBRACE attr_def attr_def_list RBRACE SEMICOLON - { - CONTEXT->ssql->flag=SCF_CREATE_TABLE;//"create_table"; - create_table_init_name(&CONTEXT->ssql->sstr.create_table, $3); - //临时变量清零 - CONTEXT->value_length = 0; - } + { + CONTEXT->ssql->flag=SCF_CREATE_TABLE;//"create_table"; + create_table_init_name(&CONTEXT->ssql->sstr.create_table, $3); + //临时变量清零 + CONTEXT->value_length = 0; + } ; attr_def_list: /* empty */ @@ -237,43 +237,34 @@ attr_def_list: ; attr_def: - ID_get type LBRACE number RBRACE - { - AttrInfo attribute; - attr_info_init(&attribute, CONTEXT->id, (AttrType)$2, $4); - create_table_append_attribute(&CONTEXT->ssql->sstr.create_table, &attribute); - CONTEXT->value_length++; - } - |ID_get type - { - AttrInfo attribute; - attr_info_init(&attribute, CONTEXT->id, (AttrType)$2, 4); - create_table_append_attribute(&CONTEXT->ssql->sstr.create_table, &attribute); - CONTEXT->value_length++; - } + ID type LBRACE number RBRACE + { + AttrInfo attribute; + attr_info_init(&attribute, $1, (AttrType)$2, $4); + create_table_append_attribute(&CONTEXT->ssql->sstr.create_table, &attribute); + CONTEXT->value_length++; + } + |ID type + { + AttrInfo attribute; + attr_info_init(&attribute, $1, (AttrType)$2, 4); + create_table_append_attribute(&CONTEXT->ssql->sstr.create_table, &attribute); + CONTEXT->value_length++; + } ; number: - NUMBER {$$ = $1;} - ; + NUMBER {$$ = $1;} + ; type: - INT_T { $$=INTS; } + INT_T { $$=INTS; } | STRING_T { $$=CHARS; } | FLOAT_T { $$=FLOATS; } ; -ID_get: - ID - { - char *temp=$1; - snprintf(CONTEXT->id, sizeof(CONTEXT->id), "%s", temp); - } - ; - - -insert: /*insert 语句的语法解析树*/ +insert: /*insert 语句的语法解析树*/ INSERT INTO ID VALUES LBRACE value value_list RBRACE SEMICOLON - { - CONTEXT->ssql->flag=SCF_INSERT;//"insert"; - inserts_init(&CONTEXT->ssql->sstr.insertion, $3, CONTEXT->values, CONTEXT->value_length); + { + CONTEXT->ssql->flag=SCF_INSERT;//"insert"; + inserts_init(&CONTEXT->ssql->sstr.insertion, $3, CONTEXT->values, CONTEXT->value_length); //临时变量清零 CONTEXT->value_length=0; @@ -282,186 +273,187 @@ insert: /*insert 语句的语法解析树*/ value_list: /* empty */ | COMMA value value_list { - // CONTEXT->values[CONTEXT->value_length++] = *$2; - } + // CONTEXT->values[CONTEXT->value_length++] = *$2; + } ; value: - NUMBER{ - value_init_integer(&CONTEXT->values[CONTEXT->value_length++], $1); - } + NUMBER{ + value_init_integer(&CONTEXT->values[CONTEXT->value_length++], $1); + } |FLOAT{ - value_init_float(&CONTEXT->values[CONTEXT->value_length++], $1); - } + value_init_float(&CONTEXT->values[CONTEXT->value_length++], $1); + } |SSS { - $1 = substr($1,1,strlen($1)-2); - value_init_string(&CONTEXT->values[CONTEXT->value_length++], $1); - } + char *tmp = substr($1,1,strlen($1)-2); + value_init_string(&CONTEXT->values[CONTEXT->value_length++], tmp); + free($1); + } ; -delete: /* delete 语句的语法解析树*/ +delete: /* delete 语句的语法解析树*/ DELETE FROM ID where SEMICOLON - { - CONTEXT->ssql->flag = SCF_DELETE;//"delete"; - deletes_init_relation(&CONTEXT->ssql->sstr.deletion, $3); - deletes_set_conditions(&CONTEXT->ssql->sstr.deletion, - CONTEXT->conditions, CONTEXT->condition_length); - CONTEXT->condition_length = 0; + { + CONTEXT->ssql->flag = SCF_DELETE;//"delete"; + deletes_init_relation(&CONTEXT->ssql->sstr.deletion, $3); + deletes_set_conditions(&CONTEXT->ssql->sstr.deletion, + CONTEXT->conditions, CONTEXT->condition_length); + CONTEXT->condition_length = 0; } ; -update: /* update 语句的语法解析树*/ +update: /* update 语句的语法解析树*/ UPDATE ID SET ID EQ value where SEMICOLON - { - CONTEXT->ssql->flag = SCF_UPDATE;//"update"; - Value *value = &CONTEXT->values[0]; - updates_init(&CONTEXT->ssql->sstr.update, $2, $4, value, - CONTEXT->conditions, CONTEXT->condition_length); - CONTEXT->condition_length = 0; - } + { + CONTEXT->ssql->flag = SCF_UPDATE;//"update"; + Value *value = &CONTEXT->values[0]; + updates_init(&CONTEXT->ssql->sstr.update, $2, $4, value, + CONTEXT->conditions, CONTEXT->condition_length); + CONTEXT->condition_length = 0; + } ; -select: /* select 语句的语法解析树*/ +select: /* select 语句的语法解析树*/ SELECT select_attr FROM ID rel_list where SEMICOLON - { - selects_append_relation(&CONTEXT->ssql->sstr.selection, $4); + { + selects_append_relation(&CONTEXT->ssql->sstr.selection, $4); - selects_append_conditions(&CONTEXT->ssql->sstr.selection, CONTEXT->conditions, CONTEXT->condition_length); + selects_append_conditions(&CONTEXT->ssql->sstr.selection, CONTEXT->conditions, CONTEXT->condition_length); - CONTEXT->ssql->flag=SCF_SELECT;//"select"; + CONTEXT->ssql->flag=SCF_SELECT;//"select"; - //临时变量清零 - CONTEXT->condition_length=0; - CONTEXT->from_length=0; - CONTEXT->select_length=0; - CONTEXT->value_length = 0; - } - ; + //临时变量清零 + CONTEXT->condition_length=0; + CONTEXT->from_length=0; + CONTEXT->select_length=0; + CONTEXT->value_length = 0; + } + ; select_attr: STAR { - RelAttr attr; - relation_attr_init(&attr, NULL, "*"); - selects_append_attribute(&CONTEXT->ssql->sstr.selection, &attr); - } + RelAttr attr; + relation_attr_init(&attr, NULL, strdup("*")); + selects_append_attribute(&CONTEXT->ssql->sstr.selection, &attr); + } | ID attr_list { - RelAttr attr; - relation_attr_init(&attr, NULL, $1); - selects_append_attribute(&CONTEXT->ssql->sstr.selection, &attr); - } - | ID DOT ID attr_list { - RelAttr attr; - relation_attr_init(&attr, $1, $3); - selects_append_attribute(&CONTEXT->ssql->sstr.selection, &attr); - } + RelAttr attr; + relation_attr_init(&attr, NULL, $1); + selects_append_attribute(&CONTEXT->ssql->sstr.selection, &attr); + } + | ID DOT ID attr_list { + RelAttr attr; + relation_attr_init(&attr, $1, $3); + selects_append_attribute(&CONTEXT->ssql->sstr.selection, &attr); + } ; attr_list: /* empty */ | COMMA ID attr_list { - RelAttr attr; - relation_attr_init(&attr, NULL, $2); - selects_append_attribute(&CONTEXT->ssql->sstr.selection, &attr); + RelAttr attr; + relation_attr_init(&attr, NULL, $2); + selects_append_attribute(&CONTEXT->ssql->sstr.selection, &attr); } | COMMA ID DOT ID attr_list { - RelAttr attr; - relation_attr_init(&attr, $2, $4); - selects_append_attribute(&CONTEXT->ssql->sstr.selection, &attr); - } - ; + RelAttr attr; + relation_attr_init(&attr, $2, $4); + selects_append_attribute(&CONTEXT->ssql->sstr.selection, &attr); + } + ; rel_list: /* empty */ - | COMMA ID rel_list { - selects_append_relation(&CONTEXT->ssql->sstr.selection, $2); - } + | COMMA ID rel_list { + selects_append_relation(&CONTEXT->ssql->sstr.selection, $2); + } ; where: /* empty */ - | WHERE condition condition_list { - // CONTEXT->conditions[CONTEXT->condition_length++]=*$2; - } + | WHERE condition condition_list { + // CONTEXT->conditions[CONTEXT->condition_length++]=*$2; + } ; condition_list: /* empty */ | AND condition condition_list { - // CONTEXT->conditions[CONTEXT->condition_length++]=*$2; - } + // CONTEXT->conditions[CONTEXT->condition_length++]=*$2; + } ; condition: ID comOp value - { - RelAttr left_attr; - relation_attr_init(&left_attr, NULL, $1); - - Value *right_value = &CONTEXT->values[CONTEXT->value_length - 1]; - - Condition condition; - condition_init(&condition, CONTEXT->comp, 1, &left_attr, NULL, 0, NULL, right_value); - CONTEXT->conditions[CONTEXT->condition_length++] = condition; - } - |value comOp value - { - Value *left_value = &CONTEXT->values[CONTEXT->value_length - 2]; - Value *right_value = &CONTEXT->values[CONTEXT->value_length - 1]; - - Condition condition; - condition_init(&condition, CONTEXT->comp, 0, NULL, left_value, 0, NULL, right_value); - CONTEXT->conditions[CONTEXT->condition_length++] = condition; - } - |ID comOp ID - { - RelAttr left_attr; - relation_attr_init(&left_attr, NULL, $1); - RelAttr right_attr; - relation_attr_init(&right_attr, NULL, $3); - - Condition condition; - condition_init(&condition, CONTEXT->comp, 1, &left_attr, NULL, 1, &right_attr, NULL); - CONTEXT->conditions[CONTEXT->condition_length++] = condition; - } + { + RelAttr left_attr; + relation_attr_init(&left_attr, NULL, $1); + + Value *right_value = &CONTEXT->values[CONTEXT->value_length - 1]; + + Condition condition; + condition_init(&condition, CONTEXT->comp, 1, &left_attr, NULL, 0, NULL, right_value); + CONTEXT->conditions[CONTEXT->condition_length++] = condition; + } + |value comOp value + { + Value *left_value = &CONTEXT->values[CONTEXT->value_length - 2]; + Value *right_value = &CONTEXT->values[CONTEXT->value_length - 1]; + + Condition condition; + condition_init(&condition, CONTEXT->comp, 0, NULL, left_value, 0, NULL, right_value); + CONTEXT->conditions[CONTEXT->condition_length++] = condition; + } + |ID comOp ID + { + RelAttr left_attr; + relation_attr_init(&left_attr, NULL, $1); + RelAttr right_attr; + relation_attr_init(&right_attr, NULL, $3); + + Condition condition; + condition_init(&condition, CONTEXT->comp, 1, &left_attr, NULL, 1, &right_attr, NULL); + CONTEXT->conditions[CONTEXT->condition_length++] = condition; + } |value comOp ID - { - Value *left_value = &CONTEXT->values[CONTEXT->value_length - 1]; - RelAttr right_attr; - relation_attr_init(&right_attr, NULL, $3); - - Condition condition; - condition_init(&condition, CONTEXT->comp, 0, NULL, left_value, 1, &right_attr, NULL); - CONTEXT->conditions[CONTEXT->condition_length++] = condition; - } + { + Value *left_value = &CONTEXT->values[CONTEXT->value_length - 1]; + RelAttr right_attr; + relation_attr_init(&right_attr, NULL, $3); + + Condition condition; + condition_init(&condition, CONTEXT->comp, 0, NULL, left_value, 1, &right_attr, NULL); + CONTEXT->conditions[CONTEXT->condition_length++] = condition; + } |ID DOT ID comOp value - { - RelAttr left_attr; - relation_attr_init(&left_attr, $1, $3); - Value *right_value = &CONTEXT->values[CONTEXT->value_length - 1]; - - Condition condition; - condition_init(&condition, CONTEXT->comp, 1, &left_attr, NULL, 0, NULL, right_value); - CONTEXT->conditions[CONTEXT->condition_length++] = condition; + { + RelAttr left_attr; + relation_attr_init(&left_attr, $1, $3); + Value *right_value = &CONTEXT->values[CONTEXT->value_length - 1]; + + Condition condition; + condition_init(&condition, CONTEXT->comp, 1, &left_attr, NULL, 0, NULL, right_value); + CONTEXT->conditions[CONTEXT->condition_length++] = condition; } |value comOp ID DOT ID - { - Value *left_value = &CONTEXT->values[CONTEXT->value_length - 1]; + { + Value *left_value = &CONTEXT->values[CONTEXT->value_length - 1]; - RelAttr right_attr; - relation_attr_init(&right_attr, $3, $5); + RelAttr right_attr; + relation_attr_init(&right_attr, $3, $5); - Condition condition; - condition_init(&condition, CONTEXT->comp, 0, NULL, left_value, 1, &right_attr, NULL); - CONTEXT->conditions[CONTEXT->condition_length++] = condition; + Condition condition; + condition_init(&condition, CONTEXT->comp, 0, NULL, left_value, 1, &right_attr, NULL); + CONTEXT->conditions[CONTEXT->condition_length++] = condition; } |ID DOT ID comOp ID DOT ID - { - RelAttr left_attr; - relation_attr_init(&left_attr, $1, $3); - RelAttr right_attr; - relation_attr_init(&right_attr, $5, $7); - - Condition condition; - condition_init(&condition, CONTEXT->comp, 1, &left_attr, NULL, 1, &right_attr, NULL); - CONTEXT->conditions[CONTEXT->condition_length++] = condition; + { + RelAttr left_attr; + relation_attr_init(&left_attr, $1, $3); + RelAttr right_attr; + relation_attr_init(&right_attr, $5, $7); + + Condition condition; + condition_init(&condition, CONTEXT->comp, 1, &left_attr, NULL, 1, &right_attr, NULL); + CONTEXT->conditions[CONTEXT->condition_length++] = condition; } ; comOp: - EQ { CONTEXT->comp = EQUAL_TO; } + EQ { CONTEXT->comp = EQUAL_TO; } | LT { CONTEXT->comp = LESS_THAN; } | GT { CONTEXT->comp = GREAT_THAN; } | LE { CONTEXT->comp = LESS_EQUAL; } @@ -470,25 +462,25 @@ comOp: ; load_data: - LOAD DATA INFILE SSS INTO TABLE ID SEMICOLON - { - CONTEXT->ssql->flag = SCF_LOAD_DATA; - load_data_init(&CONTEXT->ssql->sstr.load_data, $7, $4); - } - ; + LOAD DATA INFILE SSS INTO TABLE ID SEMICOLON + { + CONTEXT->ssql->flag = SCF_LOAD_DATA; + load_data_init(&CONTEXT->ssql->sstr.load_data, $7, $4); + } + ; %% //_____________________________________________________________________ extern void scan_string(const char *str, yyscan_t scanner); int sql_parse(const char *s, Query *sqls){ - ParserContext context; - memset(&context, 0, sizeof(context)); - - yyscan_t scanner; - yylex_init_extra(&context, &scanner); - context.ssql = sqls; - scan_string(s, scanner); - int result = yyparse(scanner); - yylex_destroy(scanner); - return result; + ParserContext context; + memset(&context, 0, sizeof(context)); + + yyscan_t scanner; + yylex_init_extra(&context, &scanner); + context.ssql = sqls; + scan_string(s, scanner); + int result = yyparse(scanner); + yylex_destroy(scanner); + return result; } diff --git a/src/observer/storage/common/field_meta.cpp b/src/observer/storage/common/field_meta.cpp index 038cdd8..90f628e 100644 --- a/src/observer/storage/common/field_meta.cpp +++ b/src/observer/storage/common/field_meta.cpp @@ -15,6 +15,7 @@ See the Mulan PSL v2 for more details. */ #include #include "storage/common/field_meta.h" #include "common/log/log.h" +#include "sql/parser/parse_defs.h" #include "json/json.h" @@ -24,25 +25,6 @@ const static Json::StaticString FIELD_OFFSET("offset"); const static Json::StaticString FIELD_LEN("len"); const static Json::StaticString FIELD_VISIBLE("visible"); -const char *ATTR_TYPE_NAME[] = {"undefined", "chars", "ints", "floats"}; - -const char *attr_type_to_string(AttrType type) -{ - if (type >= UNDEFINED && type <= FLOATS) { - return ATTR_TYPE_NAME[type]; - } - return "unknown"; -} - -AttrType attr_type_from_string(const char *s) -{ - for (unsigned int i = 0; i < sizeof(ATTR_TYPE_NAME) / sizeof(ATTR_TYPE_NAME[0]); i++) { - if (0 == strcmp(ATTR_TYPE_NAME[i], s)) { - return (AttrType)i; - } - } - return UNDEFINED; -} FieldMeta::FieldMeta() : attr_type_(AttrType::UNDEFINED), attr_offset_(-1), attr_len_(0), visible_(false) {} diff --git a/src/observer/storage/common/field_meta.h b/src/observer/storage/common/field_meta.h index 87d62e9..ad4acdd 100644 --- a/src/observer/storage/common/field_meta.h +++ b/src/observer/storage/common/field_meta.h @@ -12,8 +12,7 @@ See the Mulan PSL v2 for more details. */ // Created by Meiyi & Wangyunlai on 2021/5/12. // -#ifndef __OBSERVER_STORAGE_COMMON_FIELD_META_H__ -#define __OBSERVER_STORAGE_COMMON_FIELD_META_H__ +#pragma once #include @@ -53,4 +52,3 @@ protected: int attr_len_; bool visible_; }; -#endif // __OBSERVER_STORAGE_COMMON_FIELD_META_H__ \ No newline at end of file diff --git a/src/observer/storage/common/table.h b/src/observer/storage/common/table.h index 7bf937a..c21ec7e 100644 --- a/src/observer/storage/common/table.h +++ b/src/observer/storage/common/table.h @@ -12,8 +12,7 @@ See the Mulan PSL v2 for more details. */ // Created by Meiyi & Wangyunlai on 2021/5/12. // -#ifndef __OBSERVER_STORAGE_COMMON_TABLE_H__ -#define __OBSERVER_STORAGE_COMMON_TABLE_H__ +#pragma once #include "storage/common/table_meta.h" @@ -123,5 +122,3 @@ private: RecordFileHandler *record_handler_ = nullptr; /// 记录操作 std::vector indexes_; }; - -#endif // __OBSERVER_STORAGE_COMMON_TABLE_H__ diff --git a/src/observer/storage/common/table_meta.h b/src/observer/storage/common/table_meta.h index 19755a3..354a92d 100644 --- a/src/observer/storage/common/table_meta.h +++ b/src/observer/storage/common/table_meta.h @@ -12,8 +12,7 @@ See the Mulan PSL v2 for more details. */ // Created by Meiyi & Wangyunlai on 2021/5/12. // -#ifndef __OBSERVER_STORAGE_COMMON_TABLE_META_H__ -#define __OBSERVER_STORAGE_COMMON_TABLE_META_H__ +#pragma once #include #include @@ -73,5 +72,3 @@ protected: //@@@ TODO why used static variable? static std::vector sys_fields_; }; - -#endif // __OBSERVER_STORAGE_COMMON_TABLE_META_H__ diff --git a/src/observer/storage/default/default_storage_stage.cpp b/src/observer/storage/default/default_storage_stage.cpp index 0ce0c45..601bdbe 100644 --- a/src/observer/storage/default/default_storage_stage.cpp +++ b/src/observer/storage/default/default_storage_stage.cpp @@ -148,7 +148,7 @@ void DefaultStorageStage::handle_event(StageEvent *event) SessionEvent *session_event = sql_event->session_event(); - Session *session = session_event->get_client()->session; + Session *session = session_event->session(); Db *db = session->get_current_db(); const char *dbname = db->name(); -- GitLab