You need to sign in or sign up before continuing.
未验证 提交 e279dc7a 编写于 作者: 羽飞's avatar 羽飞 提交者: GitHub

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
上级 28eee7d5
......@@ -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")
......
......@@ -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<std::string> 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();
......
......@@ -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();
}
......@@ -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 <string.h>
#include <string>
#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__
......@@ -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 <string>
#include "common/seda/stage_event.h"
......@@ -48,4 +47,3 @@ private:
Stmt *stmt_ = nullptr;
};
#endif //__SRC_OBSERVER_SQL_EVENT_SQLEVENT_H__
......@@ -20,6 +20,7 @@ See the Mulan PSL v2 for more details. */
#include <iostream>
#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;
......
/* 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<char> 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;
}
}
}
/* 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 <string>
#include <event.h>
#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);
};
/* 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 <string.h>
#include <vector>
#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<char> &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<char> &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<char> &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<char> &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<char> &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<char> &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<char> 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<int>(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<char> 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<char> 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<int>(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<char> 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;
}
/* 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;
};
......@@ -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 <common/metrics/metrics_registry.h>
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()
......
......@@ -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__
......@@ -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 <string>
#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;
};
......@@ -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;
}
......
......@@ -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"
/**
......
......@@ -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<std::string> 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;
}
/* 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;
}
/* 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 <string>
#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_;
};
......@@ -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
......
......@@ -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_;
}
......
......@@ -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<int>(cells_.size()); }
const TupleCellSpec &cell_at(int i) const { return cells_[i]; }
private:
const char *alias_ = nullptr;
Expression *expression_ = nullptr;
std::vector<TupleCellSpec> 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<int>(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<TupleCellSpec *> speces_;
};
/*
class CompositeTuple : public Tuple
{
public:
int cell_num() const override;
RC cell_at(int index, TupleCell &cell) const = 0;
private:
int cell_num_ = 0;
std::vector<Tuple *> tuples_;
std::vector<FieldExpr *> 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<int>(speces_.size())) {
......@@ -225,7 +193,43 @@ public:
spec = speces_[index];
return RC::SUCCESS;
}
#endif
private:
std::vector<TupleCellSpec *> speces_;
Tuple *tuple_ = nullptr;
};
class ValueListTuple : public Tuple
{
public:
ValueListTuple() = default;
virtual ~ValueListTuple() = default;
void set_cells(const std::vector<TupleCell> &cells)
{
cells_ = cells;
}
virtual int cell_num() const override
{
return static_cast<int>(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<TupleCell> cells_;
};
......@@ -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_) {
......
......@@ -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:
......
......@@ -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;
......
......@@ -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 <event.h>
#include <ini_setting.h>
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;
}
}
......@@ -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);
......
......@@ -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);
// }
......@@ -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:
......
......@@ -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);
}
......@@ -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_;
......
/* 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 <vector>
class StringListOperator : public Operator
{
public:
StringListOperator()
{}
virtual ~StringListOperator() = default;
template <typename InputIt>
void append(InputIt begin, InputIt end)
{
strings_.emplace_back(begin, end);
}
void append(std::initializer_list<std::string> init)
{
strings_.emplace_back(init);
}
template <typename T>
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<TupleCell> cells;
for (const std::string &s : string_list) {
TupleCell cell(CHARS, const_cast<char *>(s.data()));
cell.set_length(s.length());
cells.push_back(cell);
}
tuple_.set_cells(cells);
return &tuple_;
}
private:
using StringList = std::vector<std::string>;
using StringListList = std::vector<StringList>;
StringListList strings_;
StringListList::iterator iterator_;
bool started_ = false;
ValueListTuple tuple_;
};
......@@ -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_;
......
......@@ -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);
......
......@@ -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 <stddef.h>
......@@ -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);
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -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;
}
......@@ -118,7 +118,7 @@ union YYSTYPE
char *string;
int number;
float floats;
char *position;
char *position;
#line 124 "yacc_sql.hpp"
......
......@@ -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> 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;
}
......@@ -15,6 +15,7 @@ See the Mulan PSL v2 for more details. */
#include <common/lang/string.h>
#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)
{}
......
......@@ -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 <string>
......@@ -53,4 +52,3 @@ protected:
int attr_len_;
bool visible_;
};
#endif // __OBSERVER_STORAGE_COMMON_FIELD_META_H__
\ No newline at end of file
......@@ -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<Index *> indexes_;
};
#endif // __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_META_H__
#define __OBSERVER_STORAGE_COMMON_TABLE_META_H__
#pragma once
#include <string>
#include <vector>
......@@ -73,5 +72,3 @@ protected:
//@@@ TODO why used static variable?
static std::vector<FieldMeta> sys_fields_;
};
#endif // __OBSERVER_STORAGE_COMMON_TABLE_META_H__
......@@ -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();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册