#include "utils.h" #include #include #include #include #include #include #include using json = nlohmann::json; using std::string; using std::vector; SQLParserRes parse_sql(const std::string& sql) { SQLParserRes res; // auto stdout_name = std::tmpnam(nullptr); // auto stderr_name = std::tmpnam(nullptr); auto stdout_name = "/tmp/sql-parser-stdout"; auto stderr_name = "/tmp/sql-parser-stderr"; auto cmd = fmt::format("xmake run sql-parser \"{}\" > {} 2> {}", sql, stdout_name, stderr_name); res.exit_code = system(cmd.c_str()); std::ifstream stdout_f(stdout_name); json stdout_j = json::parse(stdout_f); res.out = stdout_j; std::ifstream stderr_f(stderr_name); res.err.assign((std::istreambuf_iterator(stderr_f)), (std::istreambuf_iterator())); return res; } ExistTables::ExistTables(const char* file_name) { table_file_name = file_name; std::ifstream ifile(table_file_name); if (!ifile.good()) { std::ofstream ofile(table_file_name); ofile << "{}"; ofile.close(); } ifile.close(); read_from_file(); } ExistTables* ExistTables::read_from_file() { std::ifstream f(table_file_name); json j = json::parse(f); for (auto& item : j.items()) { tables[item.key()] = item.value(); } return this; }; bool ExistTables::exists(const std::string& table_name) { return tables.find(table_name) != tables.end(); } void ExistTables::set(const std::string& table_name, const TableCols& cols) { tables[table_name] = cols; } TableCols ExistTables::operator[](const std::string& table_name) { return this->get(table_name); } TableCols ExistTables::operator[](const std::vector& table_names) { return this->get(table_names); } TableCols ExistTables::get(const std::string& table_name) { return tables[table_name]; } TableCols ExistTables::get(const std::vector& table_names) { TableCols res = {}; for (let table_name : table_names) { let cols = this->get(table_name); res.assign(cols.begin(), cols.end()); } return res; } optional ExistTables::find_col_in_tables( const std::vector& table_names, const std::string col_name) { for (let table_name : table_names) { let cols = this->get(table_name); for (let col : cols) { if (col.column_name == col_name) { return col; } } } return nullopt; } void ExistTables::remove(const std::string& table_name) { tables.erase(table_name); } void ExistTables::save() { json j; for (auto& item : tables) { j[item.first] = item.second; } std::ofstream f(table_file_name); f << j.dump(2); } optional ExistTables::get_select_column_define( const vector table_names, const json& select_col) { auto type = type_of(select_col); if (type == "identifier") { return this->find_col_in_tables(table_names, select_col["value"]); } else if (type == "int" || type == "string" || type == "float") { return TableCol{.column_name = select_col["value"].dump(), .type = "const", .data_type = type, .primary_key = false}; } else if (type == "select_all_column") { return TableCol{.column_name = "*", .type = "select_all_column", .data_type = "", .primary_key = false}; } else if (type == "table_field") { let curr_table_name = select_col["table"]; let curr_field_name = select_col["field"]; if (std::find(table_names.begin(), table_names.end(), curr_table_name) == table_names.end()) { return nullopt; } return this->find_col_in_tables({curr_table_name}, curr_field_name); } return nullopt; } string select_column_get_name(const json& j) { let type = j["type"]; if (type == "identifier") { return j["value"]; } else if (type == "select_all_column") { return "select_all_column"; } else if (type == "int" || type == "string" || type == "float") { return fmt::format("{}:{}", type, j["value"]); } else if (type == "table_field") { return fmt::format("{}.{}", j["table"], j["field"]); } throw std::runtime_error( fmt::format("无法将 json 视为 select_column: {}", j.dump(2))); }