176 lines
5.3 KiB
C++
176 lines
5.3 KiB
C++
#include "usql.h"
|
|
#include "exception.h"
|
|
#include "ml_string.h"
|
|
|
|
#include <algorithm>
|
|
#include <fstream>
|
|
|
|
namespace usql {
|
|
|
|
|
|
std::unique_ptr<Table> USql::execute_create_table(const CreateTableNode &node) {
|
|
check_table_not_exists(node.table_name);
|
|
|
|
Table table{node.table_name, node.cols_defs};
|
|
m_tables.push_back(table);
|
|
|
|
execute_create_table_sys_catalogue(node);
|
|
|
|
return create_stmt_result_table(0, "table created", 0);
|
|
}
|
|
|
|
|
|
bool USql::execute_create_table_sys_catalogue(const CreateTableNode &node) {
|
|
// usql_tables
|
|
auto r = execute("insert into usql_tables(name, modified) values('" + node.table_name + "', false)");
|
|
|
|
// usql_columns
|
|
for(const ColDefNode & col_def : node.cols_defs) {
|
|
std::string i {"insert into usql_columns(table_name, column_name, column_type, column_length, nullable, column_order) values("};
|
|
i += "'" + node.table_name + "', ";
|
|
i += "'" + col_def.name + "', ";
|
|
i += "'" + column_type_name(col_def.type) + "', ";
|
|
i += std::to_string(col_def.length) + ", ";
|
|
i += (col_def.null ? "true, " : "false, ");
|
|
i += std::to_string(col_def.order);
|
|
i += ")";
|
|
|
|
auto r = execute(i);
|
|
// r->print();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
std::unique_ptr<Table> USql::execute_create_index(const CreateIndexNode &node) {
|
|
Table *table_def = find_table(node.table_name); // throws exception if not found
|
|
ColDefNode col_def = table_def->get_column_def(node.column_name); // throws exception if not found
|
|
|
|
check_index_not_exists(node.index_name);
|
|
if (col_def.null) throw Exception("index on not null supported only");
|
|
if (table_def->get_index_for_column(node.column_name) != nullptr) throw Exception("column is already indexed");
|
|
|
|
table_def->create_index({node.index_name, node.column_name, col_def.type});
|
|
|
|
table_def->index_rows(node.index_name);
|
|
|
|
execute_create_index_sys_catalogue(node);
|
|
|
|
return create_stmt_result_table(0, "index created", 0);
|
|
}
|
|
|
|
|
|
bool USql::execute_create_index_sys_catalogue(const CreateIndexNode &node) {
|
|
std::string i {"insert into usql_indexes(index_name, table_name, column_name) values("};
|
|
i += "'" + node.index_name + "', ";
|
|
i += "'" + node.table_name + "', ";
|
|
i += "'" + node.column_name + "')";
|
|
|
|
auto r = execute(i);
|
|
// r->print();
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
std::unique_ptr<Table> USql::execute_create_table_as_table(const CreateTableAsSelectNode &node) {
|
|
check_table_not_exists(node.table_name);
|
|
|
|
auto select = execute_select((SelectFromTableNode &) *node.select_table);
|
|
|
|
// create table
|
|
Table new_table{node.table_name, select->m_col_defs};
|
|
m_tables.push_back(new_table);
|
|
|
|
// copy rows
|
|
// must be here, if rows are put into new_table, they are lost during m_tables.push_table
|
|
Table *table = find_table(node.table_name);
|
|
for( Row& orig_row : select->m_rows) {
|
|
table->commit_copy_of_row(orig_row);
|
|
}
|
|
|
|
select.release(); // is it correct? hoping not to release select table here and then when releasing CreateTableAsSelectNode
|
|
|
|
return create_stmt_result_table(0, "table created", table->m_rows.size());
|
|
}
|
|
|
|
|
|
std::unique_ptr<Table> USql::execute_drop(const DropTableNode &node) {
|
|
auto name_cmp = [node](const Table& t) { return t.m_name == node.table_name; };
|
|
|
|
auto table_def = std::find_if(begin(m_tables), end(m_tables), name_cmp);
|
|
if (table_def != std::end(m_tables)) {
|
|
m_tables.erase(table_def);
|
|
return create_stmt_result_table(0, "drop succeeded", 0);
|
|
}
|
|
|
|
throw Exception("table not found (" + node.table_name + ")");
|
|
}
|
|
|
|
|
|
std::unique_ptr<Table> USql::execute_set(const SetNode &node) {
|
|
Settings::set_setting(node.name, node.value);
|
|
return create_stmt_result_table(0, "set succeeded", 1);
|
|
}
|
|
|
|
|
|
std::unique_ptr<Table> USql::execute_show(const ShowNode &node) {
|
|
std::string value = Settings::get_setting(node.name);
|
|
return create_stmt_result_table(0, "show succeeded: " + value, 1);
|
|
}
|
|
|
|
|
|
std::unique_ptr<Table> USql::create_stmt_result_table(long code, const std::string &text, size_t affected_rows) {
|
|
std::vector<ColDefNode> result_tbl_col_defs{};
|
|
result_tbl_col_defs.emplace_back("code", ColumnType::integer_type, 0, 1, false);
|
|
result_tbl_col_defs.emplace_back("desc", ColumnType::varchar_type, 1, 48, false);
|
|
result_tbl_col_defs.emplace_back("aff_rows", ColumnType::integer_type, 0, 1, true);
|
|
|
|
auto table_def = std::make_unique<Table>("result", result_tbl_col_defs);
|
|
|
|
Row& new_row = table_def->create_empty_row();
|
|
new_row.setIntColumnValue(0, code);
|
|
new_row.setStringColumnValue(1, text.size() <= 48 ? text : text.substr(0,48));
|
|
new_row.setIntColumnValue(2, (long)affected_rows);
|
|
table_def->commit_row(new_row);
|
|
|
|
return table_def;
|
|
}
|
|
|
|
|
|
|
|
std::unique_ptr<Table> USql::execute_load(const LoadIntoTableNode &node) {
|
|
// find source table
|
|
Table *table_def = find_table(node.table_name);
|
|
|
|
// read data
|
|
// std::ifstream ifs(node.filename);
|
|
// std::string content((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
|
|
// load rows
|
|
// auto rows_cnt = table_def->load_csv_string(content);
|
|
|
|
auto rows_cnt = table_def->load_csv_file(node.filename);
|
|
|
|
return create_stmt_result_table(0, "load succeeded", rows_cnt);
|
|
}
|
|
|
|
|
|
std::unique_ptr<Table> USql::execute_save(const SaveTableNode &node) {
|
|
// find source table
|
|
Table *table_def = find_table(node.table_name);
|
|
|
|
// make csv string
|
|
std::string csv_string = table_def->csv_string();
|
|
|
|
// save data
|
|
std::ofstream file(node.filename);
|
|
file << csv_string;
|
|
file.close();
|
|
|
|
return create_stmt_result_table(0, "save succeeded", table_def->rows_count());
|
|
}
|
|
|
|
|
|
} // namespace
|