usql/usql_ddl.cpp

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