int is long, select column can be function, some fixes..

just to get it work.. needs improvement
This commit is contained in:
2021-07-19 19:44:46 +02:00
parent 9afbe6435e
commit dec99b823a
14 changed files with 8697 additions and 196 deletions

119
usql.cpp
View File

@@ -1,12 +1,18 @@
#include "usql.h"
#include "exception.h"
#include "csvreader.h"
#include "ml_date.h"
#include <algorithm>
#include <fstream>
namespace usql {
USql::USql(){
m_tables.reserve(16); // some initial size, to prevent immediate reallocation
}
std::unique_ptr<Table> USql::execute(const std::string &command) {
auto node = m_parser.parse(command);
@@ -30,6 +36,8 @@ std::unique_ptr<Table> USql::execute(Node &node) {
return execute_update(static_cast<UpdateTableNode &>(node));
case NodeType::load_table:
return execute_load(static_cast<LoadIntoTableNode &>(node));
case NodeType::save_table:
return execute_save(static_cast<SaveTableNode &>(node));
default:
return create_stmt_result_table(-1, "unknown statement");
}
@@ -108,15 +116,26 @@ std::unique_ptr<Table> USql::execute_select(SelectFromTableNode &node) {
// create result table
std::vector<ColDefNode> result_tbl_col_defs{};
std::vector<int> source_table_col_index{};
int i = 0; // new column order
for (auto rc : node.cols_names) {
ColDefNode cdef = table->get_column_def(rc.name);
source_table_col_index.push_back(cdef.order);
auto col = ColDefNode(rc.name, cdef.type, i, cdef.length, cdef.null);
result_tbl_col_defs.push_back(col);
// new column order
for (int i = 0; i < node.cols_names->size(); i++) {
auto column = node.cols_names.get();
std::string new_col_name = column->operator[](i).name;
i++;
if (column->operator[](i).value->node_type == NodeType::column_name) {
ColDefNode cdef = table->get_column_def(new_col_name);
source_table_col_index.push_back(cdef.order);
auto col = ColDefNode(new_col_name, cdef.type, i, cdef.length, cdef.null);
result_tbl_col_defs.push_back(col);
} else {
// TODO replace this hardcoded values
ColDefNode cdef = ColDefNode{new_col_name, ColumnType::varchar_type, i, 64, true};
source_table_col_index.push_back(-1);
auto col = ColDefNode(new_col_name, cdef.type, i, cdef.length, cdef.null);
result_tbl_col_defs.push_back(col);
}
}
auto result = std::make_unique<Table>("result", result_tbl_col_defs);
@@ -130,14 +149,30 @@ std::unique_ptr<Table> USql::execute_select(SelectFromTableNode &node) {
// copy column values
for (auto idx = 0; idx < result->columns_count(); idx++) {
auto row_col_index = source_table_col_index[idx];
ColValue *col_value = row->ithColumn(row_col_index);
if (!col_value->isNull()) {
if (result_tbl_col_defs[idx].type == ColumnType::integer_type)
new_row.setColumnValue(idx, ((ColIntegerValue *) col_value)->integerValue());
if (result_tbl_col_defs[idx].type == ColumnType::float_type)
new_row.setColumnValue(idx, col_value->floatValue());
if (result_tbl_col_defs[idx].type == ColumnType::varchar_type)
new_row.setColumnValue(idx, col_value->stringValue());
if (row_col_index == -1) {
// todo its function TODO col_names zmenit na colValues
auto evaluated_value = evalValueNode(table, *row, node.cols_names.get()->operator[](idx).value.get());
ValueNode *col_value = evaluated_value.get();
if (true /* !col_value->isNull() */) { // TODO sjednotit nasledujici
if (result_tbl_col_defs[idx].type == ColumnType::integer_type)
new_row.setColumnValue(idx, col_value->getIntValue());
if (result_tbl_col_defs[idx].type == ColumnType::float_type)
new_row.setColumnValue(idx, col_value->getDoubleValue());
if (result_tbl_col_defs[idx].type == ColumnType::varchar_type)
new_row.setColumnValue(idx, col_value->getStringValue());
}
} else {
ColValue *col_value = row->ithColumn(row_col_index);
if (!col_value->isNull()) {
if (result_tbl_col_defs[idx].type == ColumnType::integer_type)
new_row.setColumnValue(idx, col_value->integerValue());
if (result_tbl_col_defs[idx].type == ColumnType::float_type)
new_row.setColumnValue(idx, col_value->floatValue());
if (result_tbl_col_defs[idx].type == ColumnType::varchar_type)
new_row.setColumnValue(idx, col_value->stringValue());
}
}
}
@@ -234,7 +269,7 @@ std::unique_ptr<Table> USql::execute_load(LoadIntoTableNode &node) {
// TODO validate value
if (col_def.type == ColumnType::integer_type) {
new_row.setColumnValue(col_def.order, std::stoi(csv_line[i]));
new_row.setColumnValue(col_def.order, std::stol(csv_line[i]));
} else if (col_def.type == ColumnType::float_type) {
new_row.setColumnValue(col_def.order, std::stof(csv_line[i]));
} else {
@@ -250,6 +285,41 @@ std::unique_ptr<Table> USql::execute_load(LoadIntoTableNode &node) {
}
std::unique_ptr<Table> USql::execute_save(SaveTableNode &node) {
// find source table
Table *table_def = find_table(node.table_name);
// header
std::string out_string;
for(int i = 0; i < table_def->m_col_defs.size(); i++) {
if (i > 0) out_string += ",";
out_string += table_def->m_col_defs[i].name;
}
// rows
for (auto it = table_def->m_rows.begin() + 1; it != table_def->m_rows.end(); ++it) {
std::string csv_line = "";
for(int i = 0; i < table_def->m_col_defs.size(); i++) {
if (i > 0) csv_line += ",";
auto col = it->ithColumn(i);
if (!col->isNull()) {
csv_line += col->stringValue(); // TODO handle enclosing commas etc
}
}
out_string += "\n";
out_string += csv_line;
}
// save data
std::ofstream file(node.filename);
file << out_string;
file.close();
return create_stmt_result_table(0, "save succeeded");
}
bool USql::evalWhere(Node *where, Table *table, Row &row) const {
switch (where->node_type) { // no where clause
case NodeType::true_node:
@@ -304,7 +374,7 @@ bool USql::evalRelationalOperator(const RelationalOperatorNode &filter, Table *t
std::unique_ptr<ValueNode> USql::evalValueNode(Table *table, Row &row, Node *node) const {
if (node->node_type == NodeType::database_value) {
if (node->node_type == NodeType::database_value || node->node_type == NodeType::column_name) { // TODO sjednotit
return evalDatabaseValueNode(table, row, node);
} else if (node->node_type == NodeType::int_value || node->node_type == NodeType::float_value || node->node_type == NodeType::string_value) {
@@ -374,6 +444,19 @@ std::unique_ptr<ValueNode> USql::evalFunctionValueNode(Table *table, Row &row, N
return std::make_unique<StringValueNode>(str);
}
if (fnc->function == "to_date") {
std::string date = evaluatedPars[0]->getStringValue();
std::string format = evaluatedPars[1]->getStringValue();
long epoch_time = string_to_date(date, format);
return std::make_unique<IntValueNode>(epoch_time);
}
if (fnc->function == "to_string") {
long date = evaluatedPars[0]->getIntValue();
std::string format = evaluatedPars[1]->getStringValue();
std::string formated_date = date_to_string(date, format);
return std::make_unique<StringValueNode>(formated_date);
}
throw Exception("invalid function");
}
@@ -444,7 +527,7 @@ std::unique_ptr<ValueNode> USql::evalArithmeticOperator(ColumnType outType, Arit
}
std::unique_ptr<Table> USql::create_stmt_result_table(int code, std::string text) {
std::unique_ptr<Table> USql::create_stmt_result_table(long code, std::string text) {
std::vector<ColDefNode> result_tbl_col_defs{};
result_tbl_col_defs.push_back(ColDefNode("code", ColumnType::integer_type, 0, 1, false));
result_tbl_col_defs.push_back(ColDefNode("desc", ColumnType::varchar_type, 1, 255, false));